Theory Relations

theory Relations
  imports Main "HOL-Library.LaTeXsugar" "HOL-Library.OptionalSugar"
begin

section ‹Relations›

subsection ‹Basic Conditions›

text ‹We recall the standard definitions for reflexivity, symmetry, transitivity, preoders,
        equivalence, and inverse relations.›

abbreviation "preorder Rel  preorder_on UNIV Rel"
abbreviation "equivalence Rel  equiv UNIV Rel"

text ‹A symmetric preorder is an equivalence.›

lemma symm_preorder_is_equivalence:
  fixes Rel :: "('a × 'a) set"
  assumes "preorder Rel"
      and "sym Rel"
  shows "equivalence Rel"
      using assms
      unfolding preorder_on_def equiv_def
    by simp

text ‹The symmetric closure of a relation is the union of this relation and its inverse.›

definition symcl :: "('a × 'a) set  ('a × 'a) set" where
  "symcl Rel = Rel  Rel¯"

text ‹For all (a, b) in R, the symmetric closure of R contains (a, b) as well as (b, a).›

lemma elem_of_symcl:
  fixes Rel :: "('a × 'a) set"
    and a b :: "'a"
  assumes elem: "(a, b)  Rel"
  shows "(a, b)  symcl Rel"
    and "(b, a)  symcl Rel"
    by (auto simp add: elem symcl_def)

text ‹The symmetric closure of a relation is symmetric.›

lemma sym_symcl:
  fixes Rel :: "('a × 'a) set"
  shows "sym (symcl Rel)"
    by (simp add: symcl_def sym_Un_converse)

text ‹The reflexive and symmetric closure of a relation is equal to its symmetric and reflexive
        closure.›

lemma refl_symm_closure_is_symm_refl_closure:
  fixes Rel :: "('a × 'a) set"
  shows "symcl (Rel=) = (symcl Rel)="
    by (auto simp add: symcl_def refl)

text ‹The symmetric closure of a reflexive relation is reflexive.›

lemma refl_symcl_of_refl_rel:
  fixes Rel :: "('a × 'a) set"
    and A   :: "'a set"
  assumes "refl_on A Rel"
  shows "refl_on A (symcl Rel)"
      using assms
    by (auto simp add: refl_on_def' symcl_def)

text ‹Accordingly, the reflexive, symmetric, and transitive closure of a relation is equal to its
        symmetric, reflexive, and transitive closure.›

lemma refl_symm_trans_closure_is_symm_refl_trans_closure:
  fixes Rel :: "('a × 'a) set"
  shows "(symcl (Rel=))+ = (symcl Rel)*"
      using refl_symm_closure_is_symm_refl_closure[where Rel="Rel"]
    by simp

text ‹The reflexive closure of a symmetric relation is symmetric.›

lemma sym_reflcl_of_symm_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "sym Rel"
  shows "sym (Rel=)"
      using assms
    by (simp add: sym_Id sym_Un)

text ‹The reflexive closure of a reflexive relation is the relation itself.›

lemma reflcl_of_refl_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "refl Rel"
  shows "Rel= = Rel"
      using assms
      unfolding refl_on_def
    by auto

text ‹The symmetric closure of a symmetric relation is the relation itself.›

lemma symm_closure_of_symm_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "sym Rel"
  shows "symcl Rel = Rel"
      using assms
      unfolding symcl_def sym_def
    by auto

text ‹The reflexive and transitive closure of a preorder Rel is Rel.›

lemma rtrancl_of_preorder:
  fixes Rel :: "('a × 'a) set"
  assumes "preorder Rel"
  shows "Rel* = Rel"
      using assms reflcl_of_refl_rel[of Rel] trancl_id[of "Rel="] trancl_reflcl[of Rel]
      unfolding preorder_on_def
    by auto

text ‹The reflexive and transitive closure of a relation is a subset of its reflexive, symmetric,
        and transtive closure.›

lemma refl_trans_closure_subset_of_refl_symm_trans_closure:
  fixes Rel :: "('a × 'a) set"
  shows "Rel*  (symcl (Rel=))+"
proof clarify
  fix a b
  assume "(a, b)  Rel*"
  hence "(a, b)  (symcl Rel)*"
      using in_rtrancl_UnI[of "(a, b)" "Rel" "Rel¯"]
    by (simp add: symcl_def)
  thus "(a, b)  (symcl (Rel=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[of Rel]
    by simp
qed

text ‹If a preorder Rel satisfies the following two conditions, then its symmetric closure is
        transitive:
        (1) If (a, b) and (c, b) in Rel but not (a, c) in Rel, then (b, a) in Rel or (b, c) in Rel.
        (2) If (a, b) and (a, c) in Rel but not (b, c) in Rel, then (b, a) in Rel or (c, a) in Rel.
›

lemma symm_closure_of_preorder_is_trans:
  fixes Rel :: "('a × 'a) set"
  assumes condA: "a b c. (a, b)  Rel  (c, b)  Rel  (a, c)  Rel
                   (b, a)  Rel  (b, c)  Rel"
      and condB: "a b c. (a, b)  Rel  (a, c)  Rel  (b, c)  Rel
                   (b, a)  Rel  (c, a)  Rel"
      and reflR: "refl Rel"
      and tranR: "trans Rel"
  shows "trans (symcl Rel)"
    unfolding trans_def
proof clarify
  fix a b c
  have "(a, b)  Rel; (b, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume "(a, b)  Rel" and "(b, c)  Rel"
    with tranR have "(a, c)  Rel"
        unfolding trans_def
      by blast
    thus "(a, c)  symcl Rel"
      by (simp add: symcl_def)
  qed
  moreover have "(a, b)  Rel; (c, b)  Rel; (a, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume A1: "(a, b)  Rel" and A2: "(c, b)  Rel" and "(a, c)  Rel"
    with condA have "(b, a)  Rel  (b, c)  Rel"
      by blast
    thus "(a, c)  symcl Rel"
    proof auto
      assume "(b, a)  Rel"
      with A2 tranR have "(c, a)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    next
      assume "(b, c)  Rel"
      with A1 tranR have "(a, c)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    qed
  qed
  moreover have "(b, a)  Rel; (b, c)  Rel; (a, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume B1: "(b, a)  Rel" and B2: "(b, c)  Rel" and "(a, c)  Rel"
    with condB have "(a, b)  Rel  (c, b)  Rel"
      by blast
    thus "(a, c)  symcl Rel"
    proof auto
      assume "(a, b)  Rel"
      with B2 tranR have "(a, c)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    next
      assume "(c, b)  Rel"
      with B1 tranR have "(c, a)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    qed
  qed
  moreover have "(b, a)  Rel; (c, b)  Rel  (a, c)  symcl Rel"
  proof -
    assume "(c, b)  Rel" and "(b, a)  Rel"
    with tranR have "(c, a)  Rel"
        unfolding trans_def
      by blast
    thus "(a, c)  symcl Rel"
      by (simp add: symcl_def)
  qed
  moreover assume "(a, b)  symcl Rel" and "(b, c)  symcl Rel"
  ultimately show "(a, c)  symcl Rel"
    by (auto simp add: symcl_def)
qed

subsection ‹Preservation, Reflection, and Respection of Predicates›

text ‹A relation R preserves some predicate P if P(a) implies P(b) for all (a, b) in R.›

abbreviation rel_preserves_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_preserves_pred Rel Pred  a b. (a, b)  Rel  Pred a  Pred b"

abbreviation rel_preserves_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_preserves_binary_pred Rel Pred  a b x. (a, b)  Rel  Pred a x  Pred b x"

text ‹A relation R reflects some predicate P if P(b) implies P(a) for all (a, b) in R.›

abbreviation rel_reflects_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_reflects_pred Rel Pred  a b. (a, b)  Rel  Pred b  Pred a"

abbreviation rel_reflects_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_reflects_binary_pred Rel Pred  a b x. (a, b)  Rel  Pred b x  Pred a x"

text ‹A relation respects a predicate if it preserves and reflects it.›

abbreviation rel_respects_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_respects_pred Rel Pred  rel_preserves_pred Rel Pred  rel_reflects_pred Rel Pred"

abbreviation rel_respects_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_respects_binary_pred Rel Pred 
   rel_preserves_binary_pred Rel Pred  rel_reflects_binary_pred Rel Pred"

text ‹For symmetric relations preservation, reflection, and respection of predicates means the
        same.›

lemma symm_relation_impl_preservation_equals_reflection:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes symm: "sym Rel"
  shows "rel_preserves_pred Rel Pred = rel_reflects_pred Rel Pred"
    and "rel_preserves_pred Rel Pred = rel_respects_pred Rel Pred"
    and "rel_reflects_pred Rel Pred = rel_respects_pred Rel Pred"
      using symm
      unfolding sym_def
    by blast+

lemma symm_relation_impl_preservation_equals_reflection_of_binary_predicates:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes symm: "sym Rel"
  shows "rel_preserves_binary_pred Rel Pred = rel_reflects_binary_pred Rel Pred"
    and "rel_preserves_binary_pred Rel Pred = rel_respects_binary_pred Rel Pred"
    and "rel_reflects_binary_pred Rel Pred = rel_respects_binary_pred Rel Pred"
      using symm
      unfolding sym_def
    by blast+

text ‹If a relation preserves a predicate then so does its reflexive or/and transitive closure.
›

lemma preservation_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes preservation: "rel_preserves_pred Rel Pred"
  shows "rel_preserves_pred (Rel=) Pred"
    and "rel_preserves_pred (Rel+) Pred"
    and "rel_preserves_pred (Rel*) Pred"
proof -
  from preservation show A: "rel_preserves_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_preserves_pred Rel Pred  rel_preserves_pred (Rel+) Pred"
  proof clarify
    fix Rel a b
    assume "(a, b)  Rel+" and "rel_preserves_pred Rel Pred" and "Pred a"
    thus "Pred b"
      by (induct, blast+)
  qed
  with preservation show "rel_preserves_pred (Rel+) Pred"
    by blast
  from preservation A B[where Rel="Rel="] show "rel_preserves_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by blast
qed

lemma preservation_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes preservation: "rel_preserves_binary_pred Rel Pred"
  shows "rel_preserves_binary_pred (Rel=) Pred"
    and "rel_preserves_binary_pred (Rel+) Pred"
    and "rel_preserves_binary_pred (Rel*) Pred"
proof -
  from preservation show A: "rel_preserves_binary_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_preserves_binary_pred Rel Pred
            rel_preserves_binary_pred (Rel+) Pred"
  proof clarify
    fix Rel a b x
    assume "(a, b)  Rel+" and "rel_preserves_binary_pred Rel Pred" and "Pred a x"
    thus "Pred b x"
      by (induct, blast+)
  qed
  with preservation show "rel_preserves_binary_pred (Rel+) Pred"
    by blast
  from preservation A B[where Rel="Rel="]
  show "rel_preserves_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

text ‹If a relation reflects a predicate then so does its reflexive or/and transitive closure.›

lemma reflection_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes reflection: "rel_reflects_pred Rel Pred"
  shows "rel_reflects_pred (Rel=) Pred"
    and "rel_reflects_pred (Rel+) Pred"
    and "rel_reflects_pred (Rel*) Pred"
proof -
  from reflection show A: "rel_reflects_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_reflects_pred Rel Pred  rel_reflects_pred (Rel+) Pred"
  proof clarify
    fix Rel a b
    assume "(a, b)  Rel+" and "rel_reflects_pred Rel Pred" and "Pred b"
    thus "Pred a"
      by (induct, blast+)
  qed
  with reflection show "rel_reflects_pred (Rel+) Pred"
    by blast
  from reflection A B[where Rel="Rel="] show "rel_reflects_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

lemma reflection_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes reflection: "rel_reflects_binary_pred Rel Pred"
  shows "rel_reflects_binary_pred (Rel=) Pred"
    and "rel_reflects_binary_pred (Rel+) Pred"
    and "rel_reflects_binary_pred (Rel*) Pred"
proof -
  from reflection show A: "rel_reflects_binary_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_reflects_binary_pred Rel Pred  rel_reflects_binary_pred (Rel+) Pred"
  proof clarify
    fix Rel a b x
    assume "(a, b)  Rel+" and "rel_reflects_binary_pred Rel Pred" and "Pred b x"
    thus "Pred a x"
      by (induct, blast+)
  qed
  with reflection show "rel_reflects_binary_pred (Rel+) Pred"
    by blast
  from reflection A B[where Rel="Rel="]
  show "rel_reflects_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

text ‹If a relation respects a predicate then so does its reflexive, symmetric, or/and transitive
        closure.›

lemma respection_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes respection: "rel_respects_pred Rel Pred"
  shows "rel_respects_pred (Rel=) Pred"
    and "rel_respects_pred (symcl Rel) Pred"
    and "rel_respects_pred (Rel+) Pred"
    and "rel_respects_pred (symcl (Rel=)) Pred"
    and "rel_respects_pred (Rel*) Pred"
    and "rel_respects_pred ((symcl (Rel=))+) Pred"
proof -
  from respection show A: "rel_respects_pred (Rel=) Pred"
      using preservation_and_closures(1)[where Rel="Rel" and Pred="Pred"]
            reflection_and_closures(1)[where Rel="Rel" and Pred="Pred"]
    by blast
  have B: "Rel. rel_respects_pred Rel Pred  rel_respects_pred (symcl Rel) Pred"
  proof
    fix Rel
    assume B1: "rel_respects_pred Rel Pred"
    show "rel_preserves_pred (symcl Rel) Pred"
    proof clarify
      fix a b
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred a"
      ultimately show "Pred b"
          using B1
        by blast
    qed
  next
    fix Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
    assume B2: "rel_respects_pred Rel Pred"
    show "rel_reflects_pred (symcl Rel) Pred"
    proof clarify
      fix a b
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred b"
      ultimately show "Pred a"
          using B2
        by blast
    qed
  qed
  from respection B[where Rel="Rel"] show "rel_respects_pred (symcl Rel) Pred"
    by blast
  have C: "Rel. rel_respects_pred Rel Pred  rel_respects_pred (Rel+) Pred"
  proof -
    fix Rel
    assume "rel_respects_pred Rel Pred"
    thus "rel_respects_pred (Rel+) Pred"
        using preservation_and_closures(2)[where Rel="Rel" and Pred="Pred"]
              reflection_and_closures(2)[where Rel="Rel" and Pred="Pred"]
      by blast
  qed
  from respection C[where Rel="Rel"] show "rel_respects_pred (Rel+) Pred"
    by blast
  from A B[where Rel="Rel="] show "rel_respects_pred (symcl (Rel=)) Pred"
    by blast
  from A C[where Rel="Rel="] show "rel_respects_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "rel_respects_pred ((symcl (Rel=))+) Pred"
    by blast
qed

lemma respection_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes respection: "rel_respects_binary_pred Rel Pred"
  shows "rel_respects_binary_pred (Rel=) Pred"
    and "rel_respects_binary_pred (symcl Rel) Pred"
    and "rel_respects_binary_pred (Rel+) Pred"
    and "rel_respects_binary_pred (symcl (Rel=)) Pred"
    and "rel_respects_binary_pred (Rel*) Pred"
    and "rel_respects_binary_pred ((symcl (Rel=))+) Pred"
proof -
  from respection show A: "rel_respects_binary_pred (Rel=) Pred"
      using preservation_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="Pred"]
            reflection_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="Pred"]
    by blast
  have B: "Rel. rel_respects_binary_pred Rel Pred  rel_respects_binary_pred (symcl Rel) Pred"
  proof
    fix Rel
    assume B1: "rel_respects_binary_pred Rel Pred"
    show "rel_preserves_binary_pred (symcl Rel) Pred"
    proof clarify
      fix a b x
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred a x"
      ultimately show "Pred b x"
          using B1
        by blast
    qed
  next
    fix Rel
    assume B2: "rel_respects_binary_pred Rel Pred"
    show "rel_reflects_binary_pred (symcl Rel) Pred"
    proof clarify
      fix a b x
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred b x"
      ultimately show "Pred a x"
          using B2
        by blast
    qed
  qed
  from respection B[where Rel="Rel"] show "rel_respects_binary_pred (symcl Rel) Pred"
    by blast
  have C: "Rel. rel_respects_binary_pred Rel Pred  rel_respects_binary_pred (Rel+) Pred"
  proof -
    fix Rel
    assume "rel_respects_binary_pred Rel Pred"
    thus "rel_respects_binary_pred (Rel+) Pred"
        using preservation_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="Pred"]
              reflection_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="Pred"]
      by blast
  qed
  from respection C[where Rel="Rel"] show "rel_respects_binary_pred (Rel+) Pred"
    by blast
  from A B[where Rel="Rel="]
  show "rel_respects_binary_pred (symcl (Rel=)) Pred"
    by blast
  from A C[where Rel="Rel="]
  show "rel_respects_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "rel_respects_binary_pred ((symcl (Rel=))+) Pred"
    by blast
qed

end

Theory ProcessCalculi

theory ProcessCalculi
  imports Relations
begin

section ‹Process Calculi›

text ‹A process calculus is given by a set of process terms (syntax) and a relation on terms
        (semantics). We consider reduction as well as labelled variants of the semantics.›

subsection ‹Reduction Semantics›

text ‹A set of process terms and a relation on pairs of terms (called reduction semantics) define
        a process calculus.›

record 'proc processCalculus =
  Reductions :: "'proc  'proc  bool"

text ‹A pair of the reduction relation is called a (reduction) step.›

abbreviation step :: "'proc  'proc processCalculus  'proc  bool"
    ("_ _ _" [70, 70, 70] 80)
  where
  "P Cal Q  Reductions Cal P Q"

text ‹We use * to indicate the reflexive and transitive closure of the reduction relation.›

primrec nSteps
  :: "'proc  'proc processCalculus  nat  'proc  bool"
    ("_ __ _" [70, 70, 70, 70] 80)
  where
  "P Cal0 Q     = (P = Q)" |
  "P CalSuc n Q = (P'. P Caln P'  P' Cal Q)"

definition steps
  :: "'proc  'proc processCalculus  'proc  bool"
    ("_ _* _" [70, 70, 70] 80)
  where
  "P Cal* Q  n. P Caln Q"

text ‹A process is divergent, if it can perform an infinite sequence of steps.›

definition divergent
  :: "'proc  'proc processCalculus  bool"
    ("_ _ω" [70, 70] 80)
  where
  "P (Cal)ω  P'. P Cal* P'  (P''. P' Cal P'')"

text ‹Each term can perform an (empty) sequence of steps to itself.›

lemma steps_refl:
  fixes Cal :: "'proc processCalculus"
    and P   :: "'proc"
  shows "P Cal* P"
proof -
  have "P Cal0 P"
    by simp
  hence "n. P Caln P"
    by blast
  thus "P Cal* P"
    by (simp add: steps_def)
qed

text ‹A single step is a sequence of steps of length one.›

lemma step_to_steps:
  fixes Cal  :: "'proc processCalculus"
    and P P' :: "'proc"
  assumes step: "P Cal P'"
  shows "P Cal* P'"
proof -
  from step have "P Cal1 P'"
    by simp
  thus ?thesis
    unfolding steps_def
    by blast
qed

text ‹If there is a sequence of steps from P to Q and from Q to R, then there is also a sequence
        of steps from P to R.›

lemma nSteps_add:
  fixes Cal   :: "'proc processCalculus"
    and n1 n2 :: "nat"
  shows "P Q R. P Caln1 Q  Q Caln2 R  P Cal(n1 + n2) R"
proof (induct n2, simp)
  case (Suc n)
  assume IH: "P Q R. P Caln1 Q  Q Caln R  P Cal(n1 + n) R"
  show ?case
  proof clarify
    fix P Q R
    assume "Q CalSuc n R"
    from this obtain Q' where A1: "Q Caln Q'" and A2: "Q' Cal R"
      by auto
    assume "P Caln1 Q"
    with A1 IH have "P Cal(n1 + n) Q'"
      by blast
    with A2 show "P Cal(n1 + Suc n) R"
      by auto
  qed
qed

lemma steps_add:
  fixes Cal   :: "'proc processCalculus"
    and P Q R :: "'proc"
  assumes A1: "P Cal* Q"
      and A2: "Q Cal* R"
  shows "P Cal* R"
proof -
  from A1 obtain n1 where "P Caln1 Q"
    by (auto simp add: steps_def)
  moreover from A2 obtain n2 where "Q Caln2 R"
    by (auto simp add: steps_def)
  ultimately have "P Cal(n1 + n2) R"
    using nSteps_add[where Cal="Cal"]
    by blast
  thus "P Cal* R"
    by (simp add: steps_def, blast)
qed

subsubsection ‹Observables or Barbs›

text ‹We assume a predicate that tests terms for some kind of observables. At this point we do
        not limit or restrict the kind of observables used for a calculus nor the method to check
        them.›

record ('proc, 'barbs) calculusWithBarbs =
  Calculus :: "'proc processCalculus"
  HasBarb  :: "'proc  'barbs  bool" ("__" [70, 70] 80)

abbreviation hasBarb
  :: "'proc  ('proc, 'barbs) calculusWithBarbs  'barbs  bool"
    ("_↓<_>_" [70, 70, 70] 80)
  where
  "P↓<CWB>a  HasBarb CWB P a"

text ‹A term reaches a barb if it can evolve to a term that has this barb.›

abbreviation reachesBarb
  :: "'proc  ('proc, 'barbs) calculusWithBarbs  'barbs  bool"
    ("_⇓<_>_" [70, 70, 70] 80)
  where
  "P⇓<CWB>a  P'. P (Calculus CWB)* P'  P'↓<CWB>a"

text ‹A relation R preserves barbs if whenever (P, Q) in R and P has a barb then also Q has this
        barb.›

abbreviation rel_preserves_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_preserves_barb_set Rel CWB Barbs 
   rel_preserves_binary_pred Rel (λP a. a  Barbs  P↓<CWB>a)"

abbreviation rel_preserves_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_preserves_barbs Rel CWB  rel_preserves_binary_pred Rel (HasBarb CWB)"

lemma preservation_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_preserves_barbs Rel CWB = (Barbs. rel_preserves_barb_set Rel CWB Barbs)"
    by blast

text ‹A relation R reflects barbs if whenever (P, Q) in R and Q has a barb then also P has this
        barb.›

abbreviation rel_reflects_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_reflects_barb_set Rel CWB Barbs 
   rel_reflects_binary_pred Rel (λP a. a  Barbs  P↓<CWB>a)"

abbreviation rel_reflects_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_reflects_barbs Rel CWB  rel_reflects_binary_pred Rel (HasBarb CWB)"

lemma reflection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_reflects_barbs Rel CWB = (Barbs. rel_reflects_barb_set Rel CWB Barbs)"
    by blast

text ‹A relation respects barbs if it preserves and reflects barbs.›

abbreviation rel_respects_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_respects_barb_set Rel CWB Barbs 
   rel_preserves_barb_set Rel CWB Barbs  rel_reflects_barb_set Rel CWB Barbs"

abbreviation rel_respects_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_respects_barbs Rel CWB  rel_preserves_barbs Rel CWB  rel_reflects_barbs Rel CWB"

lemma respection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_respects_barbs Rel CWB = (Barbs. rel_respects_barb_set Rel CWB Barbs)"
    by blast

text ‹If a relation preserves barbs then so does its reflexive or/and transitive closure.›

lemma preservation_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes preservation: "rel_preserves_barbs Rel CWB"
  shows "rel_preserves_barbs (Rel=) CWB"
    and "rel_preserves_barbs (Rel+) CWB"
    and "rel_preserves_barbs (Rel*) CWB"
      using preservation
            preservation_of_binary_predicates_and_closures[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast+

text ‹If a relation reflects barbs then so does its reflexive or/and transitive closure.›

lemma reflection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes reflection: "rel_reflects_barbs Rel CWB"
  shows "rel_reflects_barbs (Rel=) CWB"
    and "rel_reflects_barbs (Rel+) CWB"
    and "rel_reflects_barbs (Rel*) CWB"
      using reflection
            reflection_of_binary_predicates_and_closures[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast+

text ‹If a relation respects barbs then so does its reflexive, symmetric, or/and transitive
        closure.›

lemma respection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes respection: "rel_respects_barbs Rel CWB"
  shows "rel_respects_barbs (Rel=) CWB"
    and "rel_respects_barbs (symcl Rel) CWB"
    and "rel_respects_barbs (Rel+) CWB"
    and "rel_respects_barbs (symcl (Rel=)) CWB"
    and "rel_respects_barbs (Rel*) CWB"
    and "rel_respects_barbs ((symcl (Rel=))+) CWB"
proof -
  from respection show "rel_respects_barbs (Rel=) CWB"
      using respection_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (symcl Rel) CWB"
      using respection_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (Rel+) CWB"
      using respection_of_binary_predicates_and_closures(3)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (symcl (Rel=)) CWB"
      using respection_of_binary_predicates_and_closures(4)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (Rel*) CWB"
      using respection_of_binary_predicates_and_closures(5)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs ((symcl (Rel=))+) CWB"
      using respection_of_binary_predicates_and_closures(6)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
qed

text ‹A relation R weakly preserves barbs if it preserves reachability of barbs, i.e., if (P, Q)
        in R and P reaches a barb then also Q has to reach this barb.›

abbreviation rel_weakly_preserves_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_weakly_preserves_barb_set Rel CWB Barbs 
   rel_preserves_binary_pred Rel (λP a. a  Barbs  P⇓<CWB>a)"

abbreviation rel_weakly_preserves_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_weakly_preserves_barbs Rel CWB  rel_preserves_binary_pred Rel (λP a. P⇓<CWB>a)"

lemma weak_preservation_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_preserves_barbs Rel CWB
         = (Barbs. rel_weakly_preserves_barb_set Rel CWB Barbs)"
    by blast

text ‹A relation R weakly reflects barbs if it reflects reachability of barbs, i.e., if (P, Q) in
        R and Q reaches a barb then also P has to reach this barb.›

abbreviation rel_weakly_reflects_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_weakly_reflects_barb_set Rel CWB Barbs 
   rel_reflects_binary_pred Rel (λP a. a  Barbs  P⇓<CWB>a)"

abbreviation rel_weakly_reflects_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_weakly_reflects_barbs Rel CWB  rel_reflects_binary_pred Rel (λP a. P⇓<CWB>a)"

lemma weak_reflection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_reflects_barbs Rel CWB = (Barbs. rel_weakly_reflects_barb_set Rel CWB Barbs)"
    by blast

text ‹A relation weakly respects barbs if it weakly preserves and weakly reflects barbs.›

abbreviation rel_weakly_respects_barb_set
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool"
  where
  "rel_weakly_respects_barb_set Rel CWB Barbs 
   rel_weakly_preserves_barb_set Rel CWB Barbs  rel_weakly_reflects_barb_set Rel CWB Barbs"

abbreviation rel_weakly_respects_barbs
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "rel_weakly_respects_barbs Rel CWB 
   rel_weakly_preserves_barbs Rel CWB  rel_weakly_reflects_barbs Rel CWB"

lemma weak_respection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_respects_barbs Rel CWB = (Barbs. rel_weakly_respects_barb_set Rel CWB Barbs)"
    by blast

text ‹If a relation weakly preserves barbs then so does its reflexive or/and transitive closure.
›

lemma weak_preservation_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes preservation: "rel_weakly_preserves_barbs Rel CWB"
  shows "rel_weakly_preserves_barbs (Rel=) CWB"
    and "rel_weakly_preserves_barbs (Rel+) CWB"
    and "rel_weakly_preserves_barbs (Rel*) CWB"
      using preservation preservation_of_binary_predicates_and_closures[where Rel="Rel"
                          and Pred="λP a. P⇓<CWB>a"]
    by blast+

text ‹If a relation weakly reflects barbs then so does its reflexive or/and transitive closure.
›

lemma weak_reflection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes reflection: "rel_weakly_reflects_barbs Rel CWB"
  shows "rel_weakly_reflects_barbs (Rel=) CWB"
    and "rel_weakly_reflects_barbs (Rel+) CWB"
    and "rel_weakly_reflects_barbs (Rel*) CWB"
      using reflection reflection_of_binary_predicates_and_closures[where Rel="Rel"
                        and Pred="λP a. P⇓<CWB>a"]
    by blast+

text ‹If a relation weakly respects barbs then so does its reflexive, symmetric, or/and
        transitive closure.›

lemma weak_respection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes respection: "rel_weakly_respects_barbs Rel CWB"
  shows "rel_weakly_respects_barbs (Rel=) CWB"
    and "rel_weakly_respects_barbs (symcl Rel) CWB"
    and "rel_weakly_respects_barbs (Rel+) CWB"
    and "rel_weakly_respects_barbs (symcl (Rel=)) CWB"
    and "rel_weakly_respects_barbs (Rel*) CWB"
    and "rel_weakly_respects_barbs ((symcl (Rel=))+) CWB"
proof -
  from respection show "rel_weakly_respects_barbs (Rel=) CWB"
      using respection_of_binary_predicates_and_closures(1)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (symcl Rel) CWB"
      using respection_of_binary_predicates_and_closures(2)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (Rel+) CWB"
      using respection_of_binary_predicates_and_closures(3)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (symcl (Rel=)) CWB"
      using respection_of_binary_predicates_and_closures(4)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (Rel*) CWB"
      using respection_of_binary_predicates_and_closures(5)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs ((symcl (Rel=))+) CWB"
      using respection_of_binary_predicates_and_closures(6)[where Rel="Rel"
              and Pred="λP a. P⇓<CWB>a"]
    by blast
qed

end

Theory SimulationRelations

theory SimulationRelations
  imports ProcessCalculi
begin

section ‹Simulation Relations›

text ‹Simulation relations are a special kind of property on relations on processes. They usually
        require that steps are (strongly or weakly) preserved and/or reflected modulo the relation.
        We consider different kinds of simulation relations.›

subsection ‹Simulation›

text ‹A weak reduction simulation is relation R such that if (P, Q) in R and P evolves to some P'
        then there exists some Q' such that Q evolves to Q' and (P', Q') in R.›

abbreviation weak_reduction_simulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "weak_reduction_simulation Rel Cal 
   P Q P'. (P, Q)  Rel  P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel)"

text ‹A weak barbed simulation is weak reduction simulation that weakly preserves barbs.›

abbreviation weak_barbed_simulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_simulation Rel CWB 
   weak_reduction_simulation Rel (Calculus CWB)  rel_weakly_preserves_barbs Rel CWB"

text ‹The reflexive and/or transitive closure of a weak simulation is a weak simulation.›

lemma weak_reduction_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes simulation: "weak_reduction_simulation Rel Cal"
  shows "weak_reduction_simulation (Rel=) Cal"
    and "weak_reduction_simulation (Rel+) Cal"
    and "weak_reduction_simulation (Rel*) Cal"
proof -
  from simulation show A: "weak_reduction_simulation (Rel=) Cal"
    by (auto simp add: refl, blast)
  have B: "Rel. weak_reduction_simulation Rel Cal  weak_reduction_simulation (Rel+) Cal"
  proof clarify
    fix Rel P Q P'
    assume B1: "weak_reduction_simulation Rel Cal"
    assume "(P, Q)  Rel+" and "P Cal* P'"
    thus "Q'. Q Cal* Q'  (P', Q')  Rel+"
    proof (induct arbitrary: P')
      fix Q P'
      assume "(P, Q)  Rel" and "P Cal* P'"
      with B1 obtain Q' where "Q Cal* Q'" and "(P', Q')  Rel"
        by blast
      thus "Q'. Q Cal* Q'  (P', Q')  Rel+"
        by auto
    next
      case (step Q R P')
      assume "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel+)"
         and "P Cal* P'"
      from this obtain Q' where B2: "Q Cal* Q'" and B3: "(P', Q')  Rel+"
        by blast
      assume "(Q, R)  Rel"
      with B1 B2 obtain R' where B4: "R Cal* R'" and B5: "(Q', R')  Rel+"
        by blast
      from B3 B5 have "(P', R')  Rel+"
        by simp
      from B4 this show "R'. R Cal* R'  (P', R')  Rel+"
        by blast
    qed
  qed
  with simulation show "weak_reduction_simulation (Rel+) Cal"
    by blast
  from simulation A B[where Rel="Rel="]
  show "weak_reduction_simulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by fast
qed

lemma weak_barbed_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes simulation: "weak_barbed_simulation Rel CWB"
  shows "weak_barbed_simulation (Rel=) CWB"
    and "weak_barbed_simulation (Rel+) CWB"
    and "weak_barbed_simulation (Rel*) CWB"
proof -
  from simulation show "weak_barbed_simulation (Rel=) CWB"
      using weak_reduction_simulation_and_closures(1)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from simulation show "weak_barbed_simulation (Rel+) CWB"
      using weak_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from simulation show "weak_barbed_simulation (Rel*) CWB"
      using weak_reduction_simulation_and_closures(3)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

text ‹In the case of a simulation weak preservation of barbs can be replaced by the weaker
        condition that whenever (P, Q) in the relation and P has a barb then Q have to be able to
        reach this barb.›

abbreviation weak_barbed_preservation_cond
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_preservation_cond Rel CWB  P Q a. (P, Q)  Rel  P↓<CWB>a  Q⇓<CWB>a"

lemma weak_preservation_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes preservation: "rel_weakly_preserves_barbs Rel CWB"
  shows "weak_barbed_preservation_cond Rel CWB"
proof clarify
  fix P Q a
  have "P (Calculus CWB)* P"
    by (simp add: steps_refl)
  moreover assume "P↓<CWB>a"
  ultimately have "P⇓<CWB>a"
    by blast
  moreover assume "(P, Q)  Rel"
  ultimately show "Q⇓<CWB>a"
    using preservation
    by blast
qed

lemma simulation_impl_equality_of_preservation_of_barbs_conditions:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes simulation: "weak_reduction_simulation Rel (Calculus CWB)"
  shows "rel_weakly_preserves_barbs Rel CWB = weak_barbed_preservation_cond Rel CWB"
proof
  assume "rel_weakly_preserves_barbs Rel CWB"
  thus "weak_barbed_preservation_cond Rel CWB"
      using weak_preservation_of_barbs[where Rel="Rel" and CWB="CWB"]
    by blast
next
  assume condition: "weak_barbed_preservation_cond Rel CWB"
  show "rel_weakly_preserves_barbs Rel CWB"
  proof clarify
    fix P Q a P'
    assume "(P, Q)  Rel" and "P (Calculus CWB)* P'"
    with simulation obtain Q' where A1: "Q (Calculus CWB)* Q'" and A2: "(P', Q')  Rel"
      by blast
    assume "P'↓<CWB>a"
    with A2 condition obtain Q'' where A3: "Q' (Calculus CWB)* Q''" and A4: "Q''↓<CWB>a"
      by blast
    from A1 A3 have "Q (Calculus CWB)* Q''"
      by (rule steps_add)
    with A4 show "Q⇓<CWB>a"
      by blast
  qed
qed

text ‹A strong reduction simulation is relation R such that for each pair (P, Q) in R and each
        step of P to some P' there exists some Q' such that there is a step of Q to Q' and (P', Q')
        in R.›

abbreviation strong_reduction_simulation :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "strong_reduction_simulation Rel Cal 
   P Q P'. (P, Q)  Rel  P Cal P'  (Q'. Q Cal Q'  (P', Q')  Rel)"

text ‹A strong barbed simulation is strong reduction simulation that preserves barbs.›

abbreviation strong_barbed_simulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "strong_barbed_simulation Rel CWB 
   strong_reduction_simulation Rel (Calculus CWB)  rel_preserves_barbs Rel CWB"

text ‹A strong strong simulation is also a weak simulation.›

lemma strong_impl_weak_reduction_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes simulation: "strong_reduction_simulation Rel Cal"
  shows "weak_reduction_simulation Rel Cal"
proof clarify
  fix P Q P'
  assume A1: "(P, Q)  Rel"
  assume "P Cal* P'"
  from this obtain n where "P Caln P'"
    by (auto simp add: steps_def)
  thus "Q'. Q Cal* Q'  (P', Q')  Rel"
  proof (induct n arbitrary: P')
    case 0
    assume "P Cal0 P'"
    hence "P = P'"
      by (simp add: steps_refl)
    moreover have "Q Cal* Q"
      by (rule steps_refl)
    ultimately show "Q'. Q Cal* Q'  (P', Q')  Rel"
        using A1
      by blast
  next
    case (Suc n P'')
    assume "P CalSuc n P''"
    from this obtain P' where A2: "P CalnP'" and A3: "P' Cal P''"
      by auto
    assume "P'. P Caln P'  Q'. Q Cal* Q'  (P', Q')  Rel"
    with A2 obtain Q' where A4: "Q Cal* Q'" and A5: "(P', Q')  Rel"
      by blast
    from simulation A5 A3 obtain Q'' where A6: "Q' Cal Q''" and A7: "(P'', Q'')  Rel"
      by blast
    from A4 A6 have "Q Cal* Q''"
        using steps_add[where P="Q" and Q="Q'" and R="Q''"]
      by (simp add: step_to_steps)
    with A7 show "Q'. Q Cal* Q'  (P'', Q')  Rel"
      by blast
  qed
qed

lemma strong_barbed_simulation_impl_weak_preservation_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes simulation: "strong_barbed_simulation Rel CWB"
  shows "rel_weakly_preserves_barbs Rel CWB"
proof clarify
  fix P Q a P'
  assume "(P, Q)  Rel" and "P (Calculus CWB)* P'"
  with simulation obtain Q' where A1: "Q (Calculus CWB)* Q'" and A2: "(P', Q')  Rel"
      using strong_impl_weak_reduction_simulation[where Rel="Rel" and Cal="Calculus CWB"]
    by blast
  assume "P'↓<CWB>a"
  with simulation A2 have "Q'↓<CWB>a"
    by blast
  with A1 show "Q⇓<CWB>a"
    by blast
qed

lemma strong_impl_weak_barbed_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes simulation: "strong_barbed_simulation Rel CWB"
  shows "weak_barbed_simulation Rel CWB"
      using simulation
            strong_impl_weak_reduction_simulation[where Rel="Rel" and Cal="Calculus CWB"]
            strong_barbed_simulation_impl_weak_preservation_of_barbs[where Rel="Rel" and CWB="CWB"]
    by blast

text ‹The reflexive and/or transitive closure of a strong simulation is a strong simulation.›

lemma strong_reduction_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes simulation: "strong_reduction_simulation Rel Cal"
  shows "strong_reduction_simulation (Rel=) Cal"
    and "strong_reduction_simulation (Rel+) Cal"
    and "strong_reduction_simulation (Rel*) Cal"
proof -
  from simulation show A: "strong_reduction_simulation (Rel=) Cal"
    by (auto simp add: refl, blast)
  have B: "Rel. strong_reduction_simulation Rel Cal
            strong_reduction_simulation (Rel+) Cal"
  proof clarify
    fix Rel P Q P'
    assume B1: "strong_reduction_simulation Rel Cal"
    assume "(P, Q)  Rel+" and "P Cal P'"
    thus "Q'. Q Cal Q'  (P', Q')  Rel+"
    proof (induct arbitrary: P')
      fix Q P'
      assume "(P, Q)  Rel" and "P Cal P'"
      with B1 obtain Q' where "Q Cal Q'" and "(P', Q')  Rel"
        by blast
      thus "Q'. Q Cal Q'  (P', Q')  Rel+"
        by auto
    next
      case (step Q R P')
      assume "P'. P Cal P'  (Q'. Q Cal Q'  (P', Q')  Rel+)"
         and "P Cal P'"
      from this obtain Q' where B2: "Q Cal Q'" and B3: "(P', Q')  Rel+"
        by blast
      assume "(Q, R)  Rel"
      with B1 B2 obtain R' where B4: "R Cal R'" and B5: "(Q', R')  Rel+"
        by blast
      from B3 B5 have "(P', R')  Rel+"
        by simp
      with B4 show "R'. R Cal R'  (P', R')  Rel+"
        by blast
    qed
  qed
  with simulation show "strong_reduction_simulation (Rel+) Cal"
    by blast
  from simulation A B[where Rel="Rel="]
  show "strong_reduction_simulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by fast
qed

lemma strong_barbed_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes simulation: "strong_barbed_simulation Rel CWB"
  shows "strong_barbed_simulation (Rel=) CWB"
    and "strong_barbed_simulation (Rel+) CWB"
    and "strong_barbed_simulation (Rel*) CWB"
proof -
  from simulation show "strong_barbed_simulation (Rel=) CWB"
      using strong_reduction_simulation_and_closures(1)[where Rel="Rel" and Cal="Calculus CWB"]
            preservation_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from simulation show "strong_barbed_simulation (Rel+) CWB"
      using strong_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Calculus CWB"]
            preservation_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from simulation show "strong_barbed_simulation (Rel*) CWB"
      using strong_reduction_simulation_and_closures(3)[where Rel="Rel" and Cal="Calculus CWB"]
            preservation_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

subsection ‹Contrasimulation›

text ‹A weak reduction contrasimulation is relation R such that if (P, Q) in R and P evolves to
        some P' then there exists some Q' such that Q evolves to Q' and (Q', P') in R.›

abbreviation weak_reduction_contrasimulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "weak_reduction_contrasimulation Rel Cal 
   P Q P'. (P, Q)  Rel  P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel)"

text ‹A weak barbed contrasimulation is weak reduction contrasimulation that weakly preserves
        barbs.›

abbreviation weak_barbed_contrasimulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_contrasimulation Rel CWB 
   weak_reduction_contrasimulation Rel (Calculus CWB)  rel_weakly_preserves_barbs Rel CWB"

text ‹The reflexive and/or transitive closure of a weak contrasimulation is a weak
        contrasimulation.›

lemma weak_reduction_contrasimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes contrasimulation: "weak_reduction_contrasimulation Rel Cal"
  shows "weak_reduction_contrasimulation (Rel=) Cal"
    and "weak_reduction_contrasimulation (Rel+) Cal"
    and "weak_reduction_contrasimulation (Rel*) Cal"
proof -
  from contrasimulation show A: "weak_reduction_contrasimulation (Rel=) Cal"
    by (auto simp add: refl, blast)
  have B: "Rel. weak_reduction_contrasimulation Rel Cal
            weak_reduction_contrasimulation (Rel+) Cal"
  proof clarify
    fix Rel P Q P'
    assume B1: "weak_reduction_contrasimulation Rel Cal"
    assume "(P, Q)  Rel+" and "P Cal* P'"
    thus "Q'. Q Cal* Q'  (Q', P')  Rel+"
    proof (induct arbitrary: P')
      fix Q P'
      assume "(P, Q)  Rel" and "P Cal* P'"
      with B1 obtain Q' where "Q Cal* Q'" and "(Q', P')  Rel"
        by blast
      thus "Q'. Q Cal* Q'  (Q', P')  Rel+"
        by auto
    next
      case (step Q R P')
      assume "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel+)"
         and "P Cal* P'"
      from this obtain Q' where B2: "Q Cal* Q'" and B3: "(Q', P')  Rel+"
        by blast
      assume "(Q, R)  Rel"
      with B1 B2 obtain R' where B4: "R Cal* R'" and B5: "(R', Q')  Rel+"
        by blast
      from B5 B3 have "(R', P')  Rel+"
        by simp
      with B4 show "R'. R Cal* R'  (R', P')  Rel+"
        by blast
    qed
  qed
  with contrasimulation show "weak_reduction_contrasimulation (Rel+) Cal"
    by blast
  from contrasimulation A B[where Rel="Rel="]
  show "weak_reduction_contrasimulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by fast
qed

lemma weak_barbed_contrasimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes contrasimulation: "weak_barbed_contrasimulation Rel CWB"
  shows "weak_barbed_contrasimulation (Rel=) CWB"
    and "weak_barbed_contrasimulation (Rel+) CWB"
    and "weak_barbed_contrasimulation (Rel*) CWB"
proof -
  from contrasimulation show "weak_barbed_contrasimulation (Rel=) CWB"
      using weak_reduction_contrasimulation_and_closures(1)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from contrasimulation show "weak_barbed_contrasimulation (Rel+) CWB"
      using weak_reduction_contrasimulation_and_closures(2)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from contrasimulation show "weak_barbed_contrasimulation (Rel*) CWB"
      using weak_reduction_contrasimulation_and_closures(3)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

subsection ‹Coupled Simulation›

text ‹A weak reduction coupled simulation is relation R such that if (P, Q) in R and P evolves to
        some P' then there exists some Q' such that Q evolves to Q' and (P', Q') in R and there
        exits some Q' such that Q evolves to Q' and (Q', P') in R.›

abbreviation weak_reduction_coupled_simulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "weak_reduction_coupled_simulation Rel Cal 
   P Q P'. (P, Q)  Rel  P Cal* P'
    (Q'. Q Cal* Q'  (P', Q')  Rel)  (Q'. Q Cal* Q'  (Q', P')  Rel)"

text ‹A weak barbed coupled simulation is weak reduction coupled simulation that weakly preserves
        barbs.›

abbreviation weak_barbed_coupled_simulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_coupled_simulation Rel CWB 
   weak_reduction_coupled_simulation Rel (Calculus CWB)  rel_weakly_preserves_barbs Rel CWB"

text ‹A weak coupled simulation combines the conditions on a weak simulation and a weak
        contrasimulation.›

lemma weak_reduction_coupled_simulation_versus_simulation_and_contrasimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  shows "weak_reduction_coupled_simulation Rel Cal
         = (weak_reduction_simulation Rel Cal  weak_reduction_contrasimulation Rel Cal)"
    by blast

lemma weak_barbed_coupled_simulation_versus_simulation_and_contrasimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "weak_barbed_coupled_simulation Rel CWB
         = (weak_barbed_simulation Rel CWB  weak_barbed_contrasimulation Rel CWB)"
    by blast

text ‹The reflexive and/or transitive closure of a weak coupled simulation is a weak coupled
        simulation.›

lemma weak_reduction_coupled_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes coupledSimulation: "weak_reduction_coupled_simulation Rel Cal"
  shows "weak_reduction_coupled_simulation (Rel=) Cal"
    and "weak_reduction_coupled_simulation (Rel+) Cal"
    and "weak_reduction_coupled_simulation (Rel*) Cal"
      using weak_reduction_simulation_and_closures[where Rel="Rel" and Cal="Cal"]
            weak_reduction_contrasimulation_and_closures[where Rel="Rel" and Cal="Cal"]
            weak_reduction_coupled_simulation_versus_simulation_and_contrasimulation[where Rel="Rel"
              and Cal="Cal"]
            coupledSimulation
    by auto

lemma weak_barbed_coupled_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes coupledSimulation: "weak_barbed_coupled_simulation Rel CWB"
  shows "weak_barbed_coupled_simulation (Rel=) CWB"
    and "weak_barbed_coupled_simulation (Rel+) CWB"
    and "weak_barbed_coupled_simulation (Rel*) CWB"
proof -
  from coupledSimulation show "weak_barbed_coupled_simulation (Rel=) CWB"
      using weak_reduction_coupled_simulation_and_closures(1)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from coupledSimulation show "weak_barbed_coupled_simulation (Rel+) CWB"
      using weak_reduction_coupled_simulation_and_closures(2)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from coupledSimulation show "weak_barbed_coupled_simulation (Rel*) CWB"
      using weak_reduction_coupled_simulation_and_closures(3)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_preservation_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

subsection ‹Correspondence Simulation›

text ‹A weak reduction correspondence simulation is relation R such that
        (1) if (P, Q) in R and P evolves to some P' then there exists some Q' such that Q evolves
            to Q' and (P', Q') in R, and
        (2) if (P, Q) in R and P evolves to some P' then there exists some P'' and Q'' such that
            P evolves to P'' and Q' evolves to Q'' and (P'', Q'') in Rel.›

abbreviation weak_reduction_correspondence_simulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "weak_reduction_correspondence_simulation Rel Cal 
   (P Q P'. (P, Q)  Rel  P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel))
    (P Q Q'. (P, Q)  Rel  Q Cal* Q'
       (P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel))"

text ‹A weak barbed correspondence simulation is weak reduction correspondence simulation that
        weakly respects barbs.›

abbreviation weak_barbed_correspondence_simulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_correspondence_simulation Rel CWB 
   weak_reduction_correspondence_simulation Rel (Calculus CWB)
    rel_weakly_respects_barbs Rel CWB"

text ‹For each weak correspondence simulation R there exists a weak coupled simulation that
        contains all pairs of R in both directions.›

inductive_set cSim_cs :: "('proc × 'proc) set  'proc processCalculus  ('proc × 'proc) set"
    for Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  where
  left:  "Q Cal* Q'; (P', Q')  Rel  (P', Q)  cSim_cs Rel Cal" |
  right: "P Cal* P'; (Q, P)  Rel  (P', Q)  cSim_cs Rel Cal" |
  trans: "(P, Q)  cSim_cs Rel Cal; (Q, R)  cSim_cs Rel Cal  (P, R)  cSim_cs Rel Cal"

lemma weak_reduction_correspondence_simulation_impl_coupled_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes corrSim: "weak_reduction_correspondence_simulation Rel Cal"
  shows "weak_reduction_coupled_simulation (cSim_cs Rel Cal) Cal"
    and "P Q. (P, Q)  Rel  (P, Q)  cSim_cs Rel Cal  (Q, P)  cSim_cs Rel Cal"
proof -
  show "weak_reduction_coupled_simulation (cSim_cs Rel Cal) Cal"
  proof (rule allI, rule allI, rule allI, rule impI, erule conjE)
    fix P Q P'
    assume "(P, Q)  cSim_cs Rel Cal" and "P Cal* P'"
    thus "(Q'. Q Cal* Q'  (P', Q')  cSim_cs Rel Cal)
           (Q'. Q Cal* Q'  (Q', P')  cSim_cs Rel Cal)"
    proof (induct arbitrary: P')
      case (left Q Q' P)
      assume "(P, Q')  Rel" and "P Cal* P'"
      with corrSim obtain Q'' where A1: "Q' Cal* Q''" and A2: "(P', Q'')  Rel"
        by blast
      assume A3: "Q Cal* Q'"
      from this A1 have A4: "Q Cal* Q''"
        by (rule steps_add[where P="Q" and Q="Q'" and R="Q''"])
      have "Q'' Cal* Q''"
        by (rule steps_refl)
      with A2 have A5: "(Q'', P')  cSim_cs Rel Cal"
        by (simp add: cSim_cs.right)
      from A1 A2 have "(P', Q')  cSim_cs Rel Cal"
        by (rule cSim_cs.left)
      with A4 A5 A3 show ?case
        by blast
    next
      case (right P P' Q P'')
      assume "P Cal* P'" and "P' Cal* P''"
      hence B1: "P Cal* P''"
        by (rule steps_add[where P="P" and Q="P'" and R="P''"])
      assume B2: "(Q, P)  Rel"
      with corrSim B1 obtain Q''' P''' where B3: "Q Cal* Q'''" and B4: "P'' Cal* P'''"
                                       and B5: "(Q''', P''')  Rel"
        by blast
      from B4 B5 have B6: "(Q''', P'')  cSim_cs Rel Cal"
        by (rule cSim_cs.left)
      have B7: "Q Cal* Q"
        by (rule steps_refl)
      from B1 B2 have "(P'', Q)  cSim_cs Rel Cal"
        by (rule cSim_cs.right)
      with B3 B6 B7 show ?case
        by blast
    next
      case (trans P Q R P')
      assume "P Cal* P'"
         and "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  cSim_cs Rel Cal)
                                      (Q'. Q Cal* Q'  (Q', P')  cSim_cs Rel Cal)"
      from this obtain Q1 Q2 where C1: "Q Cal* Q1" and C2: "(Q1, P')  cSim_cs Rel Cal"
                             and C3: "Q Cal* Q2" and C4: "(P', Q2)  cSim_cs Rel Cal"
        by blast
      assume C5: "Q'. Q Cal* Q'  (R'. R Cal* R'  (Q', R')  cSim_cs Rel Cal)
                                          (R'. R Cal* R'  (R', Q')  cSim_cs Rel Cal)"
      with C1 obtain R1 where C6: "R Cal* R1" and C7: "(R1, Q1)  cSim_cs Rel Cal"
        by blast
      from C7 C2 have C8: "(R1, P')  cSim_cs Rel Cal"
        by (rule cSim_cs.trans)
      from C3 C5 obtain R2 where C9: "R Cal* R2" and C10: "(Q2, R2)  cSim_cs Rel Cal"
        by blast
      from C4 C10 have "(P', R2)  cSim_cs Rel Cal"
        by (rule cSim_cs.trans)
      with C6 C8 C9 show ?case
        by blast
    qed
  qed
next
  show "P Q. (P, Q)  Rel  (P, Q)  cSim_cs Rel Cal  (Q, P)  cSim_cs Rel Cal"
  proof clarify
    fix P Q
    have "Q Cal* Q"
      by (rule steps_refl)
    moreover assume "(P, Q)  Rel"
    ultimately show "(P, Q)  cSim_cs Rel Cal  (Q, P)  cSim_cs Rel Cal"
      by (simp add: cSim_cs.left cSim_cs.right)
  qed
qed

lemma weak_barbed_correspondence_simulation_impl_coupled_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes corrSim: "weak_barbed_correspondence_simulation Rel CWB"
  shows "weak_barbed_coupled_simulation (cSim_cs Rel (Calculus CWB)) CWB"
    and "P Q. (P, Q)  Rel  (P, Q)  cSim_cs Rel (Calculus CWB)
                                 (Q, P)  cSim_cs Rel (Calculus CWB)"
proof -
  show "weak_barbed_coupled_simulation (cSim_cs Rel (Calculus CWB)) CWB"
  proof
    from corrSim
    show "weak_reduction_coupled_simulation (cSim_cs Rel (Calculus CWB)) (Calculus CWB)"
      using weak_reduction_correspondence_simulation_impl_coupled_simulation(1)[where Rel="Rel"
            and Cal="Calculus CWB"]
    by blast
  next
    show "rel_weakly_preserves_barbs (cSim_cs Rel (Calculus CWB)) CWB"
    proof clarify
      fix P Q a P'
      assume "(P, Q)  cSim_cs Rel (Calculus CWB)" and "P (Calculus CWB)* P'" and "P'↓<CWB>a"
      thus "Q⇓<CWB>a"
      proof (induct arbitrary: P')
        case (left Q Q' P P')
        assume "(P, Q')  Rel" and "P (Calculus CWB)* P'" and "P'↓<CWB>a"
        with corrSim obtain Q'' where A1: "Q' (Calculus CWB)* Q''" and A2: "Q''↓<CWB>a"
          by blast
        assume "Q (Calculus CWB)* Q'"
        from this A1 have "Q (Calculus CWB)* Q''"
          by (rule steps_add)
        with A2 show "Q⇓<CWB>a"
          by blast
      next
        case (right P P' Q P'')
        assume "(Q, P)  Rel"
        moreover assume "P (Calculus CWB)* P'" and "P' (Calculus CWB)* P''"
        hence "P (Calculus CWB)* P''"
          by (rule steps_add)
        moreover assume "P''↓<CWB>a"
        ultimately show "Q⇓<CWB>a"
            using corrSim
          by blast
      next
        case (trans P Q R P')
        assume "P'. P (Calculus CWB)* P'  P'↓<CWB>a  Q⇓<CWB>a"
           and "P (Calculus CWB)* P'" and "P'↓<CWB>a"
           and "Q'. Q (Calculus CWB)* Q'  Q'↓<CWB>a  R⇓<CWB>a"
        thus "R⇓<CWB>a"
          by blast
      qed
    qed
  qed
next
  from corrSim show "P Q. (P, Q)  Rel  (P, Q)  cSim_cs Rel (Calculus CWB)
                                             (Q, P)  cSim_cs Rel (Calculus CWB)"
      using weak_reduction_correspondence_simulation_impl_coupled_simulation(2)[where Rel="Rel"
            and Cal="Calculus CWB"]
    by blast
qed

lemma reduction_correspondence_simulation_condition_trans:
  fixes Cal   :: "'proc processCalculus"
    and P Q R :: "'proc"
    and Rel   :: "('proc × 'proc) set"
  assumes A1: "Q'. Q Cal* Q'  (P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel)"
      and A2: "R'. R Cal* R'  (Q'' R''. Q Cal* Q''  R' Cal* R''  (Q'', R'')  Rel)"
      and A3: "weak_reduction_simulation Rel Cal"
      and A4: "trans Rel"
  shows "R'. R Cal* R'  (P'' R''. P Cal* P''  R' Cal* R''  (P'', R'')  Rel)"
proof clarify
  fix R'
  assume "R Cal* R'"
  with A2 obtain Q'' R'' where A5: "Q Cal* Q''" and A6: "R' Cal* R''"
                         and A7: "(Q'', R'')  Rel"
    by blast
  from A1 A5 obtain P''' Q''' where A8: "P Cal* P'''" and A9: "Q'' Cal* Q'''"
                              and A10: "(P''', Q''')  Rel"
    by blast
  from A3 A7 A9 obtain R''' where A11: "R'' Cal* R'''" and A12: "(Q''', R''')  Rel"
    by blast
  from A6 A11 have A13: "R' Cal* R'''"
    by (rule steps_add[where P="R'" and Q="R''" and R="R'''"])
  from A4 A10 A12 have "(P''', R''')  Rel"
      unfolding trans_def
    by blast
  with A8 A13 show "P'' R''. P Cal* P''  R' Cal* R''  (P'', R'')  Rel"
    by blast
qed

text ‹The reflexive and/or transitive closure of a weak correspondence simulation is a weak
        correspondence simulation.›

lemma weak_reduction_correspondence_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes corrSim: "weak_reduction_correspondence_simulation Rel Cal"
  shows "weak_reduction_correspondence_simulation (Rel=) Cal"
    and "weak_reduction_correspondence_simulation (Rel+) Cal"
    and "weak_reduction_correspondence_simulation (Rel*) Cal"
proof -
  show A: "weak_reduction_correspondence_simulation (Rel=) Cal"
  proof
    from corrSim show "weak_reduction_simulation (Rel=) Cal"
        using weak_reduction_simulation_and_closures(1)[where Rel="Rel" and Cal="Cal"]
      by blast
  next
    show "P Q Q'. (P, Q)  Rel=  Q Cal* Q'
           (P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel=)"
    proof clarify
      fix P Q Q'
      assume "(P, Q)  Rel=" and A1: "Q Cal* Q'"
      moreover have "P = Q  P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel="
      proof -
        assume "P = Q"
        moreover have "Q' Cal* Q'"
          by (rule steps_refl)
        ultimately show "P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel="
            using A1 refl
          by blast
      qed
      moreover
      have "(P, Q)  Rel  P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel="
      proof -
        assume "(P, Q)  Rel"
        with corrSim A1 obtain P'' Q'' where "P Cal* P''" and "Q' Cal* Q''"
                                       and "(P'', Q'')  Rel"
          by blast
        thus "P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel="
          by auto
      qed
      ultimately show "P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel="
        by auto
    qed
  qed
  have B: "Rel. weak_reduction_correspondence_simulation Rel Cal
            weak_reduction_correspondence_simulation (Rel+) Cal"
  proof
    fix Rel
    assume "weak_reduction_correspondence_simulation Rel Cal"
    thus "weak_reduction_simulation (Rel+) Cal"
        using weak_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Cal"]
      by blast
  next
    fix Rel
    assume B1: "weak_reduction_correspondence_simulation Rel Cal"
    show "P Q Q'. (P, Q)  Rel+  Q Cal* Q'
           (P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel+)"
    proof clarify
      fix P Q Q'
      assume "(P, Q)  Rel+" and "Q Cal* Q'"
      thus "P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel+"
      proof (induct arbitrary: Q')
        fix Q Q'
        assume "(P, Q)  Rel" and "Q Cal* Q'"
        with B1 obtain P'' Q'' where B2: "P Cal* P''" and B3: "Q' Cal* Q''"
                               and B4: "(P'', Q'')  Rel"
          by blast
        from B4 have "(P'', Q'')  Rel+"
          by simp
        with B2 B3 show "P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel+"
          by blast
      next
        case (step Q R R')
        assume "Q'. Q Cal* Q'
                 P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel+"
        moreover assume "(Q, R)  Rel"
        with B1
        have "R'. R Cal* R'  Q'' R''. Q Cal* Q''  R' Cal* R''  (Q'', R'')  Rel+"
          by blast
        moreover from B1 have "weak_reduction_simulation (Rel+) Cal"
            using weak_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Cal"]
          by blast
        moreover have "trans (Rel+)"
            using trans_trancl[of Rel]
          by blast
        moreover assume "R Cal* R'"
        ultimately show "P'' R''. P Cal* P''  R' Cal* R''  (P'', R'')  Rel+"
            using reduction_correspondence_simulation_condition_trans[where Rel="Rel+"]
          by blast
      qed
    qed
  qed
  from corrSim B[where Rel="Rel"] show "weak_reduction_correspondence_simulation (Rel+) Cal"
    by blast
  from A B[where Rel="Rel="]
  show "weak_reduction_correspondence_simulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by auto
qed

lemma weak_barbed_correspondence_simulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes corrSim: "weak_barbed_correspondence_simulation Rel CWB"
  shows "weak_barbed_correspondence_simulation (Rel=) CWB"
    and "weak_barbed_correspondence_simulation (Rel+) CWB"
    and "weak_barbed_correspondence_simulation (Rel*) CWB"
proof -
  from corrSim show "weak_barbed_correspondence_simulation (Rel=) CWB"
      using weak_reduction_correspondence_simulation_and_closures(1)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by fast
next
  from corrSim show "weak_barbed_correspondence_simulation (Rel+) CWB"
      using weak_reduction_correspondence_simulation_and_closures(2)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from corrSim show "weak_barbed_correspondence_simulation (Rel*) CWB"
      using weak_reduction_correspondence_simulation_and_closures(3)[where Rel="Rel"
              and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(5)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

subsection ‹Bisimulation›

text ‹A weak reduction bisimulation is relation R such that
        (1) if (P, Q) in R and P evolves to some P' then there exists some Q' such that Q evolves
            to Q' and (P', Q') in R, and
        (2) if (P, Q) in R and Q evolves to some Q' then there exists some P' such that P evolves
            to P' and (P', Q') in R.›

abbreviation weak_reduction_bisimulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "weak_reduction_bisimulation Rel Cal 
   (P Q P'. (P, Q)  Rel  P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel))
    (P Q Q'. (P, Q)  Rel  Q Cal* Q'  (P'. P Cal* P'  (P', Q')  Rel))"

text ‹A weak barbed bisimulation is weak reduction bisimulation that weakly respects barbs.›

abbreviation weak_barbed_bisimulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "weak_barbed_bisimulation Rel CWB 
   weak_reduction_bisimulation Rel (Calculus CWB)  rel_weakly_respects_barbs Rel CWB"

text ‹A symetric weak simulation is a weak bisimulation.›

lemma symm_weak_reduction_simulation_is_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes "sym Rel"
      and "weak_reduction_simulation Rel Cal"
  shows "weak_reduction_bisimulation Rel Cal"
      using assms symD[of Rel]
    by blast

lemma symm_weak_barbed_simulation_is_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes "sym Rel"
      and "weak_barbed_simulation Rel Cal"
  shows "weak_barbed_bisimulation Rel Cal"
      using assms symD[of Rel]
    by blast

text ‹If a relation as well as its inverse are weak simulations, then this relation is a weak
        bisimulation.›

lemma weak_reduction_simulations_impl_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes sim:    "weak_reduction_simulation Rel Cal"
      and simInv: "weak_reduction_simulation (Rel¯) Cal"
  shows "weak_reduction_bisimulation Rel Cal"
proof auto
  fix P Q P'
  assume "(P, Q)  Rel" and "P Cal* P'"
  with sim show "Q'. Q Cal* Q'  (P', Q')  Rel"
    by simp
next
  fix P Q Q'
  assume "(P, Q)  Rel"
  hence "(Q, P)  Rel¯"
    by simp
  moreover assume "Q Cal* Q'"
  ultimately obtain P' where A1: "P Cal* P'" and A2: "(Q', P')  Rel¯"
      using simInv
    by blast
  from A2 have "(P', Q')  Rel"
    by induct
  with A1 show "P'. P Cal* P'  (P', Q')  Rel"
    by blast
qed

lemma weak_reduction_bisimulations_impl_inverse_is_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "weak_reduction_bisimulation Rel Cal"
  shows "weak_reduction_simulation (Rel¯) Cal"
proof clarify
  fix P Q P'
  assume "(Q, P)  Rel"
  moreover assume "P Cal* P'"
  ultimately obtain Q' where A1: "Q Cal* Q'" and A2: "(Q', P')  Rel"
      using bisim
    by blast
  from A2 have "(P', Q')  Rel¯"
    by simp
  with A1 show "Q'. Q Cal* Q'  (P', Q')  Rel¯"
    by blast
qed

lemma weak_reduction_simulations_iff_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  shows "(weak_reduction_simulation Rel Cal  weak_reduction_simulation (Rel¯) Cal)
         = weak_reduction_bisimulation Rel Cal"
      using weak_reduction_simulations_impl_bisimulation[where Rel="Rel" and Cal="Cal"]
            weak_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel" and Cal="Cal"]
    by blast

lemma weak_barbed_simulations_iff_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "(weak_barbed_simulation Rel CWB  weak_barbed_simulation (Rel¯) CWB)
         = weak_barbed_bisimulation Rel CWB"
proof (rule iffI, erule conjE)
  assume sim: "weak_barbed_simulation Rel CWB"
     and rev: "weak_barbed_simulation (Rel¯) CWB"
  hence "weak_reduction_bisimulation Rel (Calculus CWB)"
      using weak_reduction_simulations_impl_bisimulation[where Rel="Rel" and Cal="Calculus CWB"]
    by blast
  moreover from sim have "rel_weakly_preserves_barbs Rel CWB"
    by simp
  moreover from rev have "rel_weakly_reflects_barbs Rel CWB"
    by simp
  ultimately show "weak_barbed_bisimulation Rel CWB"
    by blast
next
  assume bisim: "weak_barbed_bisimulation Rel CWB"
  hence "weak_barbed_simulation Rel CWB"
    by blast
  moreover from bisim have "weak_reduction_simulation (Rel¯) (Calculus CWB)"
      using weak_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel"]
    by simp
  moreover from bisim have "rel_weakly_reflects_barbs Rel CWB"
    by blast
  hence "rel_weakly_preserves_barbs (Rel¯) CWB"
    by simp
  ultimately show "weak_barbed_simulation Rel CWB  weak_barbed_simulation (Rel¯) CWB"
    by blast
qed

text ‹A weak bisimulation is a weak correspondence simulation.›

lemma weak_reduction_bisimulation_is_correspondence_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "weak_reduction_bisimulation Rel Cal"
  shows "weak_reduction_correspondence_simulation Rel Cal"
proof
  from bisim show "weak_reduction_simulation Rel Cal"
    by blast
next
  show "P Q Q'. (P, Q)  Rel  Q Cal* Q'
         (P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel)"
  proof clarify
    fix P Q Q'
    assume "(P, Q)  Rel" and "Q Cal* Q'"
    with bisim obtain P' where "P Cal* P'" and "(P', Q')  Rel"
      by blast
    moreover have "Q' Cal* Q'"
      by (rule steps_refl)
    ultimately show "(P'' Q''. P Cal* P''  Q' Cal* Q''  (P'', Q'')  Rel)"
      by blast
  qed
qed

lemma weak_barbed_bisimulation_is_correspondence_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes bisim: "weak_barbed_bisimulation Rel CWB"
  shows "weak_barbed_correspondence_simulation Rel CWB"
      using bisim weak_reduction_bisimulation_is_correspondence_simulation[where Rel="Rel"
                   and Cal="Calculus CWB"]
    by blast

text ‹The reflexive, symmetric, and/or transitive closure of a weak bisimulation is a weak
        bisimulation.›

lemma weak_reduction_bisimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "weak_reduction_bisimulation Rel Cal"
  shows "weak_reduction_bisimulation (Rel=) Cal"
    and "weak_reduction_bisimulation (symcl Rel) Cal"
    and "weak_reduction_bisimulation (Rel+) Cal"
    and "weak_reduction_bisimulation (symcl (Rel=)) Cal"
    and "weak_reduction_bisimulation (Rel*) Cal"
    and "weak_reduction_bisimulation ((symcl (Rel=))+) Cal"
proof -
  from bisim show A: "weak_reduction_bisimulation (Rel=) Cal"
    by (auto simp add: refl, blast+)
  have B: "Rel. weak_reduction_bisimulation Rel Cal
            weak_reduction_bisimulation (symcl Rel) Cal"
    by (auto simp add: symcl_def, blast+)
  from bisim B[where Rel="Rel"] show "weak_reduction_bisimulation (symcl Rel) Cal"
    by blast
  have C: "Rel. weak_reduction_bisimulation Rel Cal
            weak_reduction_bisimulation (Rel+) Cal"
  proof
    fix Rel
    assume "weak_reduction_bisimulation Rel Cal"
    thus "weak_reduction_simulation (Rel+) Cal"
        using weak_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Cal"]
      by blast
  next
    fix Rel
    assume C1: "weak_reduction_bisimulation Rel Cal"
    show "P Q Q'. (P, Q)  Rel+  Q Cal* Q'
           (P'. P Cal* P'  (P', Q')  Rel+)"
    proof clarify
      fix P Q Q'
      assume "(P, Q)  Rel+" and "Q Cal* Q'"
      thus "P'. P Cal* P'  (P', Q')  Rel+"
      proof (induct arbitrary: Q')
        fix Q Q'
        assume "(P, Q)  Rel" and "Q Cal* Q'"
        with C1 obtain P' where "P Cal* P'" and "(P', Q')  Rel"
          by blast
        thus "P'. P Cal* P'  (P', Q')  Rel+"
          by auto
      next
        case (step Q R R')
        assume "(Q, R)  Rel" and "R Cal* R'"
        with C1 obtain Q' where C2: "Q Cal* Q'" and C3: "(Q', R')  Rel+"
          by blast
        assume "Q'. Q Cal* Q'  P'. P Cal* P'  (P', Q')  Rel+"
        with C2 obtain P' where C4: "P Cal* P'" and C5: "(P', Q')  Rel+"
          by blast
        from C5 C3 have "(P', R')  Rel+"
          by simp
        with C4 show "P'. P Cal* P'  (P', R')  Rel+"
          by blast
      qed
    qed
  qed
  from bisim C[where Rel="Rel"] show "weak_reduction_bisimulation (Rel+) Cal"
    by blast
  from A B[where Rel="Rel="] show "weak_reduction_bisimulation (symcl (Rel=)) Cal"
    by blast
  from A C[where Rel="Rel="] show "weak_reduction_bisimulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by auto
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "weak_reduction_bisimulation ((symcl (Rel=))+) Cal"
    by blast
qed

lemma weak_barbed_bisimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes bisim: "weak_barbed_bisimulation Rel CWB"
  shows "weak_barbed_bisimulation (Rel=) CWB"
    and "weak_barbed_bisimulation (symcl Rel) CWB"
    and "weak_barbed_bisimulation (Rel+) CWB"
    and "weak_barbed_bisimulation (symcl (Rel=)) CWB"
    and "weak_barbed_bisimulation (Rel*) CWB"
    and "weak_barbed_bisimulation ((symcl (Rel=))+) CWB"
proof -
  from bisim show "weak_barbed_bisimulation (Rel=) CWB"
      using weak_reduction_bisimulation_and_closures(1)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by fast
next
  from bisim show "weak_barbed_bisimulation (symcl Rel) CWB"
      using weak_reduction_bisimulation_and_closures(2)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "weak_barbed_bisimulation (Rel+) CWB"
      using weak_reduction_bisimulation_and_closures(3)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "weak_barbed_bisimulation (symcl (Rel=)) CWB"
      using weak_reduction_bisimulation_and_closures(4)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(4)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "weak_barbed_bisimulation (Rel*) CWB"
      using weak_reduction_bisimulation_and_closures(5)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(5)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "weak_barbed_bisimulation ((symcl (Rel=))+) CWB"
      using weak_reduction_bisimulation_and_closures(6)[where Rel="Rel" and Cal="Calculus CWB"]
            weak_respection_of_barbs_and_closures(6)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

text ‹A strong reduction bisimulation is relation R such that
        (1) if (P, Q) in R and P' is a derivative of P then there exists some Q' such that Q' is a
            derivative of Q and (P', Q') in R, and
        (2) if (P, Q) in R and Q' is a derivative of Q then there exists some P' such that P' is a
            derivative of P and (P', Q') in R.›

abbreviation strong_reduction_bisimulation
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "strong_reduction_bisimulation Rel Cal 
   (P Q P'. (P, Q)  Rel  P Cal P'  (Q'. Q Cal Q'  (P', Q')  Rel))
    (P Q Q'. (P, Q)  Rel  Q Cal Q'  (P'. P Cal P'  (P', Q')  Rel))"

text ‹A strong barbed bisimulation is strong reduction bisimulation that respects barbs.›

abbreviation strong_barbed_bisimulation
    :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool"
  where
  "strong_barbed_bisimulation Rel CWB 
   strong_reduction_bisimulation Rel (Calculus CWB)  rel_respects_barbs Rel CWB"

text ‹A symetric strong simulation is a strong bisimulation.›

lemma symm_strong_reduction_simulation_is_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes "sym Rel"
      and "strong_reduction_simulation Rel Cal"
  shows "strong_reduction_bisimulation Rel Cal"
      using assms symD[of Rel]
    by blast

lemma symm_strong_barbed_simulation_is_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes "sym Rel"
      and "strong_barbed_simulation Rel CWB"
  shows "strong_barbed_bisimulation Rel CWB"
      using assms symD[of Rel]
    by blast

text ‹If a relation as well as its inverse are strong simulations, then this relation is a strong
        bisimulation.›

lemma strong_reduction_simulations_impl_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes sim:    "strong_reduction_simulation Rel Cal"
      and simInv: "strong_reduction_simulation (Rel¯) Cal"
  shows "strong_reduction_bisimulation Rel Cal"
proof auto
  fix P Q P'
  assume "(P, Q)  Rel" and "P Cal P'"
  with sim show "Q'. Q Cal Q'  (P', Q')  Rel"
    by simp
next
  fix P Q Q'
  assume "(P, Q)  Rel"
  hence "(Q, P)  Rel¯"
    by simp
  moreover assume "Q Cal Q'"
  ultimately obtain P' where A1: "P Cal P'" and A2: "(Q', P')  Rel¯"
      using simInv
    by blast
  from A2 have "(P', Q')  Rel"
    by induct
  with A1 show "P'. P Cal P'  (P', Q')  Rel"
    by blast
qed

lemma strong_reduction_bisimulations_impl_inverse_is_simulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "strong_reduction_bisimulation Rel Cal"
  shows "strong_reduction_simulation (Rel¯) Cal"
proof clarify
  fix P Q P'
  assume "(Q, P)  Rel"
  moreover assume "P Cal P'"
  ultimately obtain Q' where A1: "Q Cal Q'" and A2: "(Q', P')  Rel"
      using bisim
    by blast
  from A2 have "(P', Q')  Rel¯"
    by simp
  with A1 show "Q'. Q Cal Q'  (P', Q')  Rel¯"
    by blast
qed

lemma strong_reduction_simulations_iff_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  shows "(strong_reduction_simulation Rel Cal  strong_reduction_simulation (Rel¯) Cal)
         = strong_reduction_bisimulation Rel Cal"
      using strong_reduction_simulations_impl_bisimulation[where Rel="Rel" and Cal="Cal"]
            strong_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel"]
    by blast

lemma strong_barbed_simulations_iff_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "(strong_barbed_simulation Rel CWB  strong_barbed_simulation (Rel¯) CWB)
         = strong_barbed_bisimulation Rel CWB"
proof (rule iffI, erule conjE)
  assume sim: "strong_barbed_simulation Rel CWB"
     and rev: "strong_barbed_simulation (Rel¯) CWB"
  hence "strong_reduction_bisimulation Rel (Calculus CWB)"
      using strong_reduction_simulations_impl_bisimulation[where Rel="Rel" and Cal="Calculus CWB"]
    by blast
  moreover from sim have "rel_preserves_barbs Rel CWB"
    by simp
  moreover from rev have "rel_reflects_barbs Rel CWB"
    by simp
  ultimately show "strong_barbed_bisimulation Rel CWB"
    by blast
next
  assume bisim: "strong_barbed_bisimulation Rel CWB"
  hence "strong_barbed_simulation Rel CWB"
    by blast
  moreover from bisim have "strong_reduction_simulation (Rel¯) (Calculus CWB)"
      using strong_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel"]
    by simp
  moreover from bisim have "rel_reflects_barbs Rel CWB"
    by blast
  hence "rel_preserves_barbs (Rel¯) CWB"
    by simp
  ultimately
  show "strong_barbed_simulation Rel CWB  strong_barbed_simulation (Rel¯) CWB"
    by blast
qed

text ‹A strong bisimulation is a weak bisimulation.›

lemma strong_impl_weak_reduction_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "strong_reduction_bisimulation Rel Cal"
  shows "weak_reduction_bisimulation Rel Cal"
proof
  from bisim show "weak_reduction_simulation Rel Cal"
      using strong_impl_weak_reduction_simulation[where Rel="Rel" and Cal="Cal"]
    by blast
next
  show "P Q Q'. (P, Q)  Rel  Q Cal* Q'  (P'. P Cal* P'  (P', Q')  Rel)"
  proof clarify
    fix P Q Q'
    assume A1: "(P, Q)  Rel"
    assume "Q Cal* Q'"
    from this obtain n where "Q Caln Q'"
      by (auto simp add: steps_def)
    thus "P'. P Cal* P'  (P', Q')  Rel"
    proof (induct n arbitrary: Q')
      case 0
      assume "Q Cal0 Q'"
      hence "Q = Q'"
        by (simp add: steps_refl)
      moreover have "P Cal* P"
        by (rule steps_refl)
      ultimately show "P'. P Cal* P'  (P', Q')  Rel"
          using A1
        by blast
    next
      case (Suc n Q'')
      assume "Q CalSuc n Q''"
      from this obtain Q' where A2: "Q CalnQ'" and A3: "Q' Cal Q''"
        by auto
      assume "Q'. Q Caln Q'  P'. P Cal* P'  (P', Q')  Rel"
      with A2 obtain P' where A4: "P Cal* P'" and A5: "(P', Q')  Rel"
        by blast
      from bisim A5 A3 obtain P'' where A6: "P' Cal P''" and A7: "(P'', Q'')  Rel"
        by blast
      from A4 A6 have "P Cal* P''"
          using steps_add[where P="P" and Q="P'" and R="P''"]
        by (simp add: step_to_steps)
      with A7 show "P'. P Cal* P'  (P', Q'')  Rel"
        by blast
    qed
  qed
qed

lemma strong_barbed_bisimulation_impl_weak_respection_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes bisim: "strong_barbed_bisimulation Rel CWB"
  shows "rel_weakly_respects_barbs Rel CWB"
proof
  from bisim show "rel_weakly_preserves_barbs Rel CWB"
      using strong_barbed_simulation_impl_weak_preservation_of_barbs[where Rel="Rel" and CWB="CWB"]
    by blast
next
  show "rel_weakly_reflects_barbs Rel CWB"
  proof clarify
    fix P Q a Q'
    assume "(P, Q)  Rel" and "Q (Calculus CWB)* Q'"
    with bisim obtain P' where A1: "P (Calculus CWB)* P'" and A2: "(P', Q')  Rel"
        using strong_impl_weak_reduction_bisimulation[where Rel="Rel" and Cal="Calculus CWB"]
      by blast
    assume "Q'↓<CWB>a"
    with bisim A2 have "P'↓<CWB>a"
      by blast
    with A1 show "P⇓<CWB>a"
      by blast
  qed
qed

lemma strong_impl_weak_barbed_bisimulation:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes bisim: "strong_barbed_bisimulation Rel CWB"
  shows "weak_barbed_bisimulation Rel CWB"
      using bisim
            strong_impl_weak_reduction_bisimulation[where Rel="Rel" and Cal="Calculus CWB"]
            strong_barbed_bisimulation_impl_weak_respection_of_barbs[where Rel="Rel" and CWB="CWB"]
    by blast

text ‹The reflexive, symmetric, and/or transitive closure of a strong bisimulation is a strong
        bisimulation.›

lemma strong_reduction_bisimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and Cal :: "'proc processCalculus"
  assumes bisim: "strong_reduction_bisimulation Rel Cal"
  shows "strong_reduction_bisimulation (Rel=) Cal"
    and "strong_reduction_bisimulation (symcl Rel) Cal"
    and "strong_reduction_bisimulation (Rel+) Cal"
    and "strong_reduction_bisimulation (symcl (Rel=)) Cal"
    and "strong_reduction_bisimulation (Rel*) Cal"
    and "strong_reduction_bisimulation ((symcl (Rel=))+) Cal"
proof -
  from bisim show A: "strong_reduction_bisimulation (Rel=) Cal"
    by (auto simp add: refl, blast+)
  have B: "Rel. strong_reduction_bisimulation Rel Cal
            strong_reduction_bisimulation (symcl Rel) Cal"
    by (auto simp add: symcl_def, blast+)
  from bisim B[where Rel="Rel"] show "strong_reduction_bisimulation (symcl Rel) Cal"
    by blast
  have C: "Rel. strong_reduction_bisimulation Rel Cal
            strong_reduction_bisimulation (Rel+) Cal"
  proof
    fix Rel
    assume "strong_reduction_bisimulation Rel Cal"
    thus "strong_reduction_simulation (Rel+) Cal"
        using strong_reduction_simulation_and_closures(2)[where Rel="Rel" and Cal="Cal"]
      by blast
  next
    fix Rel
    assume C1: "strong_reduction_bisimulation Rel Cal"
    show "P Q Q'. (P, Q)  Rel+  Q Cal Q'
           (P'. P Cal P'  (P', Q')  Rel+)"
    proof clarify
      fix P Q Q'
      assume "(P, Q)  Rel+" and "Q Cal Q'"
      thus "P'. P Cal P'  (P', Q')  Rel+"
      proof (induct arbitrary: Q')
        fix Q Q'
        assume "(P, Q)  Rel" and "Q Cal Q'"
        with C1 obtain P' where "P Cal P'" and "(P', Q')  Rel"
          by blast
        thus "P'. P Cal P'  (P', Q')  Rel+"
          by auto
      next
        case (step Q R R')
        assume "(Q, R)  Rel" and "R Cal R'"
        with C1 obtain Q' where C2: "Q Cal Q'" and C3: "(Q', R')  Rel+"
          by blast
        assume "Q'. Q Cal Q'  P'. P Cal P'  (P', Q')  Rel+"
        with C2 obtain P' where C4: "P Cal P'" and C5: "(P', Q')  Rel+"
          by blast
        from C5 C3 have "(P', R')  Rel+"
          by simp
        with C4 show "P'. P Cal P'  (P', R')  Rel+"
          by blast
      qed
    qed
  qed
  from bisim C[where Rel="Rel"] show "strong_reduction_bisimulation (Rel+) Cal"
    by blast
  from A B[where Rel="Rel="]
  show "strong_reduction_bisimulation (symcl (Rel=)) Cal"
    by blast
  from A C[where Rel="Rel="]
  show "strong_reduction_bisimulation (Rel*) Cal"
      using trancl_reflcl[of Rel]
    by auto
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "strong_reduction_bisimulation ((symcl (Rel=))+) Cal"
    by blast
qed

lemma strong_barbed_bisimulation_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes bisim: "strong_barbed_bisimulation Rel CWB"
  shows "strong_barbed_bisimulation (Rel=) CWB"
    and "strong_barbed_bisimulation (symcl Rel) CWB"
    and "strong_barbed_bisimulation (Rel+) CWB"
    and "strong_barbed_bisimulation (symcl (Rel=)) CWB"
    and "strong_barbed_bisimulation (Rel*) CWB"
    and "strong_barbed_bisimulation ((symcl (Rel=))+) CWB"
proof -
  from bisim show "strong_barbed_bisimulation (Rel=) CWB"
      using strong_reduction_bisimulation_and_closures(1)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(1)[where Rel="Rel" and CWB="CWB"]
    by fast
next
  from bisim show "strong_barbed_bisimulation (symcl Rel) CWB"
      using strong_reduction_bisimulation_and_closures(2)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(2)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "strong_barbed_bisimulation (Rel+) CWB"
      using strong_reduction_bisimulation_and_closures(3)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(3)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "strong_barbed_bisimulation (symcl (Rel=)) CWB"
      using strong_reduction_bisimulation_and_closures(4)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(4)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "strong_barbed_bisimulation (Rel*) CWB"
      using strong_reduction_bisimulation_and_closures(5)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(5)[where Rel="Rel" and CWB="CWB"]
    by blast
next
  from bisim show "strong_barbed_bisimulation ((symcl (Rel=))+) CWB"
      using strong_reduction_bisimulation_and_closures(6)[where Rel="Rel" and Cal="Calculus CWB"]
            respection_of_barbs_and_closures(6)[where Rel="Rel" and CWB="CWB"]
    by blast
qed

subsection ‹Step Closure of Relations›

text ‹The step closure of a relation on process terms is the transitive closure of the union of
        the relation and the inverse of the reduction relation of the respective calculus.›

inductive_set stepsClosure :: "('a × 'a) set  'a processCalculus  ('a × 'a) set"
    for Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  where
  rel:   "(P, Q)  Rel  (P, Q)  stepsClosure Rel Cal" |
  steps: "P Cal* P'  (P', P)  stepsClosure Rel Cal" |
  trans: "(P, Q)  stepsClosure Rel Cal; (Q, R)  stepsClosure Rel Cal
           (P, R)  stepsClosure Rel Cal"

abbreviation stepsClosureInfix ::
    "'a  ('a × 'a) set  'a processCalculus  'a  bool" ("_ ℛ↦<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ℛ↦<Rel,Cal> Q  (P, Q)  stepsClosure Rel Cal"

text ‹Applying the steps closure twice does not change the relation.›

lemma steps_closure_of_steps_closure:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  shows "stepsClosure (stepsClosure Rel Cal) Cal = stepsClosure Rel Cal"
proof auto
  fix P Q
  assume "P ℛ↦<stepsClosure Rel Cal,Cal> Q"
  thus "P ℛ↦<Rel,Cal> Q"
  proof induct
    case (rel P Q)
    assume "P ℛ↦<Rel,Cal> Q"
    thus "P ℛ↦<Rel,Cal> Q"
      by simp
  next
    case (steps P P')
    assume "P Cal* P'"
    thus "P' ℛ↦<Rel,Cal> P"
      by (rule stepsClosure.steps)
  next
    case (trans P Q R)
    assume "P ℛ↦<Rel,Cal> Q" and "Q ℛ↦<Rel,Cal> R"
    thus "P ℛ↦<Rel,Cal> R"
      by (rule stepsClosure.trans)
  qed
next
  fix P Q
  assume "P ℛ↦<Rel,Cal> Q"
  thus "P ℛ↦<stepsClosure Rel Cal,Cal> Q"
    by (rule stepsClosure.rel)
qed

text ‹The steps closure is a preorder.›

lemma stepsClosure_refl:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  shows "refl (stepsClosure Rel Cal)"
    unfolding refl_on_def
proof auto
  fix P
  have "P Cal* P"
    by (rule steps_refl)
  thus "P ℛ↦<Rel,Cal> P"
    by (rule stepsClosure.steps)
qed

lemma refl_trans_closure_of_rel_impl_steps_closure:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
    and P Q :: "'a"
  assumes "(P, Q)  Rel*"
  shows "P ℛ↦<Rel,Cal> Q"
    using assms
proof induct
  show "P ℛ↦<Rel,Cal> P"
      using stepsClosure_refl[of Rel Cal]
      unfolding refl_on_def
    by simp
next
  case (step Q R)
  assume "(Q, R)  Rel" and "P ℛ↦<Rel,Cal> Q"
  thus "P ℛ↦<Rel,Cal> R"
      using stepsClosure.rel[of Q R Rel Cal] stepsClosure.trans[of P Q Rel Cal R]
    by blast
qed

text ‹The steps closure of a relation is always a weak reduction simulation.›

lemma steps_closure_is_weak_reduction_simulation:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  shows "weak_reduction_simulation (stepsClosure Rel Cal) Cal"
proof clarify
  fix P Q P'
  assume "P ℛ↦<Rel,Cal> Q" and "P Cal* P'"
  thus "Q'. Q Cal* Q'  P' ℛ↦<Rel,Cal> Q'"
  proof (induct arbitrary: P')
    case (rel P Q)
    assume "P Cal* P'"
    hence "P' ℛ↦<Rel,Cal> P"
      by (rule stepsClosure.steps)
    moreover assume "(P, Q)  Rel"
    hence "P ℛ↦<Rel,Cal> Q"
      by (simp add: stepsClosure.rel)
    ultimately have "P' ℛ↦<Rel,Cal> Q"
      by (rule stepsClosure.trans)
    thus "Q'. Q Cal* Q'  P' ℛ↦<Rel,Cal> Q'"
        using steps_refl[where Cal="Cal" and P="Q"]
      by blast
  next
    case (steps P P' P'')
    assume "P Cal* P'" and "P' Cal* P''"
    hence "P Cal* P''"
      by (rule steps_add)
    moreover have "P'' ℛ↦<Rel,Cal> P''"
        using stepsClosure_refl[where Rel="Rel" and Cal="Cal"]
        unfolding refl_on_def
      by simp
    ultimately show "Q'. P Cal* Q'  P'' ℛ↦<Rel,Cal> Q'"
      by blast
  next
    case (trans P Q R)
    assume "P Cal* P'"
       and "P'. P Cal* P'  Q'. Q Cal* Q'  P' ℛ↦<Rel,Cal> Q'"
    from this obtain Q' where A1: "Q Cal* Q'" and A2: "P' ℛ↦<Rel,Cal> Q'"
      by blast
    assume "Q'. Q Cal* Q'  R'. R Cal* R'  Q' ℛ↦<Rel,Cal> R'"
    with A1 obtain R' where A3: "R Cal* R'" and A4: "Q' ℛ↦<Rel,Cal> R'"
      by blast
    from A2 A4 have "P' ℛ↦<Rel,Cal> R'"
      by (rule stepsClosure.trans)
    with A3 show "R'. R Cal* R'  P' ℛ↦<Rel,Cal> R'"
      by blast
  qed
qed

text ‹If Rel is a weak simulation and its inverse is a weak contrasimulation, then the steps
        closure of Rel is a contrasimulation.›

lemma inverse_contrasimulation_impl_reverse_pair_in_steps_closure:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
    and P Q :: "'a"
  assumes con:  "weak_reduction_contrasimulation (Rel¯) Cal"
      and pair: "(P, Q)  Rel"
  shows "Q ℛ↦<Rel,Cal> P"
proof -
  from pair have "(Q, P)  Rel¯"
    by simp
  moreover have "Q Cal* Q"
    by (rule steps_refl)
  ultimately obtain P' where A1: "P Cal* P'" and A2: "(P', Q)  Rel¯"
      using con
    by blast
  from A2 have "Q ℛ↦<Rel,Cal> P'"
    by (simp add: stepsClosure.rel)
  moreover from A1 have "P' ℛ↦<Rel,Cal> P"
    by (rule stepsClosure.steps)
  ultimately show "Q ℛ↦<Rel,Cal> P"
    by (rule stepsClosure.trans)
qed

lemma simulation_and_inverse_contrasimulation_impl_steps_closure_is_contrasimulation:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  assumes sim: "weak_reduction_simulation Rel Cal"
      and con: "weak_reduction_contrasimulation (Rel¯) Cal"
  shows "weak_reduction_contrasimulation (stepsClosure Rel Cal) Cal"
proof clarify
  fix P Q P'
  assume "P ℛ↦<Rel,Cal> Q" and "P Cal* P'"
  thus "Q'. Q Cal* Q'  Q' ℛ↦<Rel,Cal> P'"
  proof (induct arbitrary: P')
    case (rel P Q)
    assume "(P, Q)  Rel" and "P Cal* P'"
    with sim obtain Q' where A1: "Q Cal* Q'" and A2: "(P', Q')  Rel"
      by blast
    from A2 con have "Q' ℛ↦<Rel,Cal> P'"
        using inverse_contrasimulation_impl_reverse_pair_in_steps_closure[where Rel="Rel"]
      by blast
    with A1 show "Q'. Q Cal* Q'  Q' ℛ↦<Rel,Cal> P'"
      by blast
  next
    case (steps P P' P'')
    assume "P Cal* P'" and "P' Cal* P''"
    hence "P Cal* P''"
      by (rule steps_add)
    thus "Q'. P Cal* Q'  Q' ℛ↦<Rel,Cal> P''"
        using stepsClosure_refl[where Rel="Rel" and Cal="Cal"]
        unfolding refl_on_def
      by blast
  next
    case (trans P Q R)
    assume "P'. P Cal* P'  Q'. Q Cal* Q'  Q' ℛ↦<Rel,Cal> P'"
       and "P Cal* P'"
    from this obtain Q' where A1: "Q Cal* Q'" and A2: "Q' ℛ↦<Rel,Cal> P'"
      by blast
    assume "Q'. Q Cal* Q'  R'. R Cal* R'  R' ℛ↦<Rel,Cal> Q'"
    with A1 obtain R' where A3: "R Cal* R'" and A4: "R' ℛ↦<Rel,Cal> Q'"
      by blast
    from A4 A2 have "R' ℛ↦<Rel,Cal> P'"
      by (rule stepsClosure.trans)
    with A3 show "R'. R Cal* R'  R' ℛ↦<Rel,Cal> P'"
      by blast
  qed
qed

text ‹Accordingly, if Rel is a weak simulation and its inverse is a weak contrasimulation, then
        the steps closure of Rel is a coupled simulation.›

lemma simulation_and_inverse_contrasimulation_impl_steps_closure_is_coupled_simulation:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
  assumes sim: "weak_reduction_simulation Rel Cal"
      and con: "weak_reduction_contrasimulation (Rel¯) Cal"
  shows "weak_reduction_coupled_simulation (stepsClosure Rel Cal) Cal"
      using sim con simulation_and_inverse_contrasimulation_impl_steps_closure_is_contrasimulation
            steps_closure_is_weak_reduction_simulation[where Rel="Rel" and Cal="Cal"]
    by simp

text ‹If the relation that is closed under steps is a (contra)simulation, then we can conlude
        from a pair in the closure on a pair in the original relation.›

lemma stepsClosure_simulation_impl_refl_trans_closure_of_Rel:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
    and P Q :: "'a"
  assumes A1: "P ℛ↦<Rel,Cal> Q"
      and A2: "weak_reduction_simulation Rel Cal"
  shows "Q'. Q Cal* Q'  (P, Q')  Rel*"
proof -
  have "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
    using A1
  proof induct
    case (rel P Q)
    assume "(P, Q)  Rel"
    with A2 have "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel)"
      by blast
    thus "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
      by blast
  next
    case (steps P P')
    assume A: "P Cal* P'"
    show "P''. P' Cal* P''  (Q'. P Cal* Q'  (P'', Q')  Rel*)"
    proof clarify
      fix P''
      assume "P' Cal* P''"
      with A have "P Cal* P''"
        by (rule steps_add)
      moreover have "(P'', P'')  Rel*"
        by simp
      ultimately show "Q'. P Cal* Q'  (P'', Q')  Rel*"
        by blast
    qed
  next
    case (trans P Q R)
    assume A1: "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
       and A2: "Q'. Q Cal* Q'  (R'. R Cal* R'  (Q', R')  Rel*)"
    show "P'. P Cal* P'  (R'. R Cal* R'  (P', R')  Rel*)"
    proof clarify
      fix P'
      assume "P Cal* P'"
      with A1 obtain Q' where A3: "Q Cal* Q'" and A4: "(P', Q')  Rel*"
        by blast
      from A2 A3 obtain R' where A5: "R Cal* R'" and A6: "(Q', R')  Rel*"
        by blast
      from A4 A6 have "(P', R')  Rel*"
        by simp
      with A5 show "R'. R Cal* R'  (P', R')  Rel*"
        by blast
    qed
  qed
  moreover have "P Cal* P"
    by (rule steps_refl)
  ultimately show ?thesis
    by blast
qed

lemma stepsClosure_contrasimulation_impl_refl_trans_closure_of_Rel:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
    and P Q :: "'a"
  assumes A1: "P ℛ↦<Rel,Cal> Q"
      and A2: "weak_reduction_contrasimulation Rel Cal"
  shows "Q'. Q Cal* Q'  (Q', P)  Rel*"
proof -
  have "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel*)"
    using A1
  proof induct
    case (rel P Q)
    assume "(P, Q)  Rel"
    with A2 have "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel)"
      by blast
    thus "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel*)"
      by blast
  next
    case (steps P P')
    assume A: "P Cal* P'"
    show "P''. P' Cal* P''  (Q'. P Cal* Q'  (Q', P'')  Rel*)"
    proof clarify
      fix P''
      assume "P' Cal* P''"
      with A have "P Cal* P''"
        by (rule steps_add)
      moreover have "(P'', P'')  Rel*"
        by simp
      ultimately show "Q'. P Cal* Q'  (Q', P'')  Rel*"
        by blast
    qed
  next
    case (trans P Q R)
    assume A1: "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel*)"
       and A2: "Q'. Q Cal* Q'  (R'. R Cal* R'  (R', Q')  Rel*)"
    show "P'. P Cal* P'  (R'. R Cal* R'  (R', P')  Rel*)"
    proof clarify
      fix P'
      assume "P Cal* P'"
      with A1 obtain Q' where A3: "Q Cal* Q'" and A4: "(Q', P')  Rel*"
        by blast
      from A2 A3 obtain R' where A5: "R Cal* R'" and A6: "(R', Q')  Rel*"
        by blast
      from A4 A6 have "(R', P')  Rel*"
        by simp
      with A5 show "R'. R Cal* R'  (R', P')  Rel*"
        by blast
    qed
  qed
  moreover have "P Cal* P"
    by (rule steps_refl)
  ultimately show ?thesis
    by blast
qed

lemma stepsClosure_contrasimulation_of_inverse_impl_refl_trans_closure_of_Rel:
  fixes Rel :: "('a × 'a) set"
    and Cal :: "'a processCalculus"
    and P Q :: "'a"
  assumes A1: "P ℛ↦<Rel¯,Cal> Q"
      and A2: "weak_reduction_contrasimulation (Rel¯) Cal"
  shows "Q'. Q Cal* Q'  (P, Q')  Rel*"
proof -
  have "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
    using A1
  proof induct
    case (rel P Q)
    assume "(P, Q)  Rel¯"
    with A2 have "P'. P Cal* P'  (Q'. Q Cal* Q'  (Q', P')  Rel¯)"
      by blast
    thus "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
      by blast
  next
    case (steps P P')
    assume A: "P Cal* P'"
    show "P''. P' Cal* P''  (Q'. P Cal* Q'  (P'', Q')  Rel*)"
    proof clarify
      fix P''
      assume "P' Cal* P''"
      with A have "P Cal* P''"
        by (rule steps_add)
      moreover have "(P'', P'')  Rel*"
        by simp
      ultimately show "Q'. P Cal* Q'  (P'', Q')  Rel*"
        by blast
    qed
  next
    case (trans P Q R)
    assume A1: "P'. P Cal* P'  (Q'. Q Cal* Q'  (P', Q')  Rel*)"
       and A2: "Q'. Q Cal* Q'  (R'. R Cal* R'  (Q', R')  Rel*)"
    show "P'. P Cal* P'  (R'. R Cal* R'  (P', R')  Rel*)"
    proof clarify
      fix P'
      assume "P Cal* P'"
      with A1 obtain Q' where A3: "Q Cal* Q'" and A4: "(P', Q')  Rel*"
        by blast
      from A3 A2 obtain R' where A5: "R Cal* R'" and A6: "(Q', R')  Rel*"
        by blast
      from A4 A6 have "(P', R')  Rel*"
        by simp
      with A5 show "R'. R Cal* R'  (P', R')  Rel*"
        by blast
    qed
  qed
  moreover have "P Cal* P"
    by (rule steps_refl)
  ultimately show ?thesis
    by blast
qed

end

Theory Encodings

theory Encodings
  imports ProcessCalculi
begin

section ‹Encodings›

text ‹In the simplest case an encoding from a source into a target language is a mapping from
        source into target terms. Encodability criteria describe properties on such mappings. To
        analyse encodability criteria we map them on conditions on relations between source and
        target terms. More precisely, we consider relations on pairs of the disjoint union of
        source and target terms. We denote this disjoint union of source and target terms by Proc.
›

datatype ('procS, 'procT) Proc =
  SourceTerm 'procS |
  TargetTerm 'procT

definition STCal
    :: "'procS processCalculus  'procT processCalculus
         (('procS, 'procT) Proc) processCalculus"
  where
  "STCal Source Target 
   Reductions = λP P'.
   (SP SP'. P = SourceTerm SP  P' = SourceTerm SP'  Reductions Source SP SP') 
   (TP TP'. P = TargetTerm TP  P' = TargetTerm TP'  Reductions Target TP TP')"

definition STCalWB
    :: "('procS, 'barbs) calculusWithBarbs  ('procT, 'barbs) calculusWithBarbs
         (('procS, 'procT) Proc, 'barbs) calculusWithBarbs"
  where
  "STCalWB Source Target 
   Calculus = STCal (calculusWithBarbs.Calculus Source) (calculusWithBarbs.Calculus Target),
   HasBarb   = λP a. (SP. P = SourceTerm SP  (calculusWithBarbs.HasBarb Source) SP a) 
                     (TP. P = TargetTerm TP  (calculusWithBarbs.HasBarb Target) TP a)"

text ‹An encoding consists of a source language, a target language, and a mapping from source
        into target terms.›

locale encoding =
  fixes Source :: "'procS processCalculus"
    and Target :: "'procT processCalculus"
    and Enc    :: "'procS  'procT"
begin

abbreviation enc :: "'procS  'procT" ("_" [65] 70) where
  "S  Enc S"

abbreviation isSource :: "('procS, 'procT) Proc  bool" ("_  ProcS" [70] 80) where
  "P  ProcS  (S. P = SourceTerm S)"

abbreviation isTarget :: "('procS, 'procT) Proc  bool" ("_  ProcT" [70] 80) where
  "P  ProcT  (T. P = TargetTerm T)"

abbreviation getSource
    :: "'procS  ('procS, 'procT) Proc  bool" ("_ ∈S _" [70, 70] 80)
  where
  "S ∈S P  (P = SourceTerm S)"

abbreviation getTarget
    :: "'procT  ('procS, 'procT) Proc  bool" ("_ ∈T _" [70, 70] 80)
  where
  "T ∈T P  (P = TargetTerm T)"

text ‹A step of a term in Proc is either a source term step or a target term step.›

abbreviation stepST
    :: "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ⟼ST _" [70, 70] 80)
  where
  "P ⟼ST P' 
   (S S'. S ∈S P  S' ∈S P'  S Source S')  (T T'. T ∈T P  T' ∈T P'  T Target T')"

lemma stepST_STCal_step:
  fixes P P' :: "('procS, 'procT) Proc"
  shows "P (STCal Source Target) P' = P ⟼ST P'"
    by (simp add: STCal_def)

lemma STStep_step:
  fixes S  :: "'procS"
    and T  :: "'procT"
    and P' :: "('procS, 'procT) Proc"
  shows "SourceTerm S ⟼ST P' = (S'. S' ∈S P'  S Source S')"
    and "TargetTerm T ⟼ST P' = (T'. T' ∈T P'  T Target T')"
    by blast+

lemma STCal_step:
  fixes S  :: "'procS"
    and T  :: "'procT"
    and P' :: "('procS, 'procT) Proc"
  shows "SourceTerm S (STCal Source Target) P' = (S'. S' ∈S P'  S Source S')"
    and "TargetTerm T (STCal Source Target) P' = (T'. T' ∈T P'  T Target T')"
    by (simp add: STCal_def)+

text ‹A sequence of steps of a term in Proc is either a sequence of source term steps or a
        sequence of target term steps.›

abbreviation stepsST
    :: "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ⟼ST* _" [70, 70] 80)
  where
  "P ⟼ST* P' 
   (S S'. S ∈S P  S' ∈S P'  S Source* S')  (T T'. T ∈T P  T' ∈T P'  T Target* T')"

lemma STSteps_steps:
  fixes S  :: "'procS"
    and T  :: "'procT"
    and P' :: "('procS, 'procT) Proc"
  shows "SourceTerm S ⟼ST* P' = (S'. S' ∈S P'  S Source* S')"
    and "TargetTerm T ⟼ST* P' = (T'. T' ∈T P'  T Target* T')"
    by blast+

lemma STCal_steps:
  fixes S  :: "'procS"
    and T  :: "'procT"
    and P' :: "('procS, 'procT) Proc"
  shows "SourceTerm S (STCal Source Target)* P' = (S'. S' ∈S P'  S Source* S')"
    and "TargetTerm T (STCal Source Target)* P' = (T'. T' ∈T P'  T Target* T')"
proof auto
  assume "SourceTerm S (STCal Source Target)* P'"
  from this obtain n where "SourceTerm S (STCal Source Target)n P'"
    by (auto simp add: steps_def)
  thus "S'. S' ∈S P'  S Source* S'"
  proof (induct n arbitrary: P')
    case 0
    assume "SourceTerm S (STCal Source Target)0 P'"
    hence "S ∈S P'"
      by simp
    moreover have "S Source* S"
      by (rule steps_refl)
    ultimately show "S'. S' ∈S P'  S Source* S'"
      by blast
  next
    case (Suc n P'')
    assume "SourceTerm S (STCal Source Target)Suc n P''"
    from this obtain P' where A1: "SourceTerm S (STCal Source Target)n P'"
                          and A2: "P' (STCal Source Target) P''"
      by auto
    assume "P'. SourceTerm S (STCal Source Target)n P'  S'. S' ∈S P'  S Source* S'"
    with A1 obtain S' where A3: "S' ∈S P'" and A4: "S Source* S'"
      by blast
    from A2 A3 obtain S'' where A5: "S'' ∈S P''" and A6: "S' Source S''"
        using STCal_step(1)[where S="S'" and P'="P''"]
      by blast
    from A4 A6 have "S Source* S''"
        using step_to_steps[where Cal="Source" and P="S'" and P'="S''"]
      by (simp add: steps_add[where Cal="Source" and P="S" and Q="S'" and R="S''"])
    with A5 show "S''. S'' ∈S P''  S Source* S''"
      by blast
  qed
next
  fix S'
  assume "S Source* S'"
  from this obtain n where "S Sourcen S'"
    by (auto simp add: steps_def)
  thus "SourceTerm S (STCal Source Target)* (SourceTerm S')"
  proof (induct n arbitrary: S')
    case 0
    assume "S Source0 S'"
    hence "S = S'"
      by auto
    thus "SourceTerm S (STCal Source Target)* (SourceTerm S')"
      by (simp add: steps_refl)
  next
    case (Suc n S'')
    assume "S SourceSuc n S''"
    from this obtain S' where B1: "S Sourcen S'" and B2: "S' Source S''"
      by auto
    assume "S'. S Sourcen S'  SourceTerm S (STCal Source Target)* (SourceTerm S')"
    with B1 have "SourceTerm S (STCal Source Target)* (SourceTerm S')"
      by blast
    moreover from B2 have "SourceTerm S' (STCal Source Target)* (SourceTerm S'')"
        using step_to_steps[where Cal="STCal Source Target" and P="SourceTerm S'"]
      by (simp add: STCal_def)
    ultimately show "SourceTerm S (STCal Source Target)* (SourceTerm S'')"
      by (rule steps_add)
  qed
next
  assume "TargetTerm T (STCal Source Target)* P'"
  from this obtain n where "TargetTerm T (STCal Source Target)n P'"
    by (auto simp add: steps_def)
  thus "T'. T' ∈T P'  T Target* T'"
  proof (induct n arbitrary: P')
    case 0
    assume "TargetTerm T (STCal Source Target)0 P'"
    hence "T ∈T P'"
      by simp
    moreover have "T Target* T"
      by (rule steps_refl)
    ultimately show "T'. T' ∈T P'  T Target* T'"
      by blast
  next
    case (Suc n P'')
    assume "TargetTerm T (STCal Source Target)Suc n P''"
    from this obtain P' where A1: "TargetTerm T (STCal Source Target)n P'"
                          and A2: "P' (STCal Source Target) P''"
      by auto
    assume "P'. TargetTerm T (STCal Source Target)n P'  T'. T' ∈T P'  T Target* T'"
    with A1 obtain T' where A3: "T' ∈T P'" and A4: "T Target* T'"
      by blast
    from A2 A3 obtain T'' where A5: "T'' ∈T P''" and A6: "T' Target T''"
        using STCal_step(2)[where T="T'" and P'="P''"]
      by blast
    from A4 A6 have "T Target* T''"
        using step_to_steps[where Cal="Target" and P="T'" and P'="T''"]
      by (simp add: steps_add[where Cal="Target" and P="T" and Q="T'" and R="T''"])
    with A5 show "T''. T'' ∈T P''  T Target* T''"
      by blast
  qed
next
  fix T'
  assume "T Target* T'"
  from this obtain n where "T Targetn T'"
    by (auto simp add: steps_def)
  thus "TargetTerm T (STCal Source Target)* (TargetTerm T')"
  proof (induct n arbitrary: T')
    case 0
    assume "T Target0 T'"
    hence "T = T'"
      by auto
    thus "TargetTerm T (STCal Source Target)* (TargetTerm T')"
      by (simp add: steps_refl)
  next
    case (Suc n T'')
    assume "T TargetSuc n T''"
    from this obtain T' where B1: "T Targetn T'" and B2: "T' Target T''"
      by auto
    assume "T'. T Targetn T'  TargetTerm T (STCal Source Target)* (TargetTerm T')"
    with B1 have "TargetTerm T (STCal Source Target)* (TargetTerm T')"
      by blast
    moreover from B2 have "TargetTerm T' (STCal Source Target)* (TargetTerm T'')"
        using step_to_steps[where Cal="STCal Source Target" and P="TargetTerm T'"]
      by (simp add: STCal_def)
    ultimately show "TargetTerm T (STCal Source Target)* (TargetTerm T'')"
      by (rule steps_add)
  qed
qed

lemma stepsST_STCal_steps:
  fixes P P' :: "('procS, 'procT) Proc"
  shows "P (STCal Source Target)* P' = P ⟼ST* P'"
proof (cases P)
  case (SourceTerm SP)
  assume "SP ∈S P"
  thus "P (STCal Source Target)* P' = P ⟼ST* P'"
      using STCal_steps(1)[where S="SP" and P'="P'"] STSteps_steps(1)[where S="SP" and P'="P'"]
    by blast
next
  case (TargetTerm TP)
  assume "TP ∈T P"
  thus "P (STCal Source Target)* P' = P ⟼ST* P'"
      using STCal_steps(2)[where T="TP" and P'="P'"] STSteps_steps(2)[where T="TP" and P'="P'"]
    by blast
qed

lemma stepsST_refl:
  fixes P :: "('procS, 'procT) Proc"
  shows "P ⟼ST* P"
    by (cases P, simp_all add: steps_refl)

lemma stepsST_add:
  fixes P Q R :: "('procS, 'procT) Proc"
  assumes A1: "P ⟼ST* Q"
      and A2: "Q ⟼ST* R"
  shows "P ⟼ST* R"
proof -
  from A1 have "P (STCal Source Target)* Q"
    by (simp add: stepsST_STCal_steps)
  moreover from A2 have "Q (STCal Source Target)* R"
    by (simp add: stepsST_STCal_steps)
  ultimately have "P (STCal Source Target)* R"
    by (rule steps_add)
  thus "P ⟼ST* R"
    by (simp add: stepsST_STCal_steps)
qed

text ‹A divergent term of Proc is either a divergent source term or a divergent target term.›

abbreviation divergentST
    :: "('procS, 'procT) Proc  bool" ("_ ⟼STω" [70] 80)
  where
  "P ⟼STω  (S. S ∈S P  S (Source)ω)  (T. T ∈T P  T (Target)ω)"

lemma STCal_divergent:
  fixes S  :: "'procS"
    and T  :: "'procT"
  shows "SourceTerm S (STCal Source Target)ω = S (Source)ω"
    and "TargetTerm T (STCal Source Target)ω = T (Target)ω"
      using STCal_steps
    by (auto simp add: STCal_def divergent_def)

lemma divergentST_STCal_divergent:
  fixes P :: "('procS, 'procT) Proc"
  shows "P (STCal Source Target)ω = P ⟼STω"
proof (cases P)
  case (SourceTerm SP)
  assume "SP ∈S P"
  thus "P (STCal Source Target)ω = P ⟼STω"
      using STCal_divergent(1)
    by simp
next
  case (TargetTerm TP)
  assume "TP ∈T P"
  thus "P (STCal Source Target)ω = P ⟼STω"
      using STCal_divergent(2)
    by simp
qed

text ‹Similar to relations we define what it means for an encoding to preserve, reflect, or
        respect a predicate. An encoding preserves some predicate P if P(S) implies P(enc S) for
        all source terms S.›

abbreviation enc_preserves_pred :: "(('procS, 'procT) Proc  bool)  bool" where
  "enc_preserves_pred Pred  S. Pred (SourceTerm S)  Pred (TargetTerm (S))"

abbreviation enc_preserves_binary_pred
    :: "(('procS, 'procT) Proc  'b  bool)  bool"
  where
  "enc_preserves_binary_pred Pred  S x. Pred (SourceTerm S) x  Pred (TargetTerm (S)) x"

text ‹An encoding reflects some predicate P if P(S) implies P(enc S) for all source terms S.›

abbreviation enc_reflects_pred :: "(('procS, 'procT) Proc  bool)  bool" where
  "enc_reflects_pred Pred  S. Pred (TargetTerm (S))  Pred (SourceTerm S)"

abbreviation enc_reflects_binary_pred
    :: "(('procS, 'procT) Proc  'b  bool)  bool"
  where
  "enc_reflects_binary_pred Pred  S x. Pred (TargetTerm (S)) x  Pred (SourceTerm S) x"

text ‹An encoding respects a predicate if it preserves and reflects it.›

abbreviation enc_respects_pred :: "(('procS, 'procT) Proc  bool)  bool" where
  "enc_respects_pred Pred  enc_preserves_pred Pred  enc_reflects_pred Pred"

abbreviation enc_respects_binary_pred
    :: "(('procS, 'procT) Proc  'b  bool)  bool"
  where
  "enc_respects_binary_pred Pred 
   enc_preserves_binary_pred Pred  enc_reflects_binary_pred Pred"

end

text ‹To compare source terms and target terms w.r.t. their barbs or observables we assume that
        each languages defines its own predicate for the existence of barbs.›

locale encoding_wrt_barbs =
  encoding Source Target Enc
  for Source :: "'procS processCalculus"
  and Target :: "'procT processCalculus"
  and Enc    :: "'procS  'procT" +
  fixes SWB :: "('procS, 'barbs) calculusWithBarbs"
    and TWB :: "('procT, 'barbs) calculusWithBarbs"
  assumes calS: "calculusWithBarbs.Calculus SWB = Source"
      and calT: "calculusWithBarbs.Calculus TWB = Target"
begin

lemma STCalWB_STCal:
  shows "Calculus (STCalWB SWB TWB) = STCal Source Target"
      unfolding STCalWB_def using calS calT
    by auto

text ‹We say a term P of Proc has some barbs a if either P is a source term that has barb a or P
        is a target term that has the barb b. For simplicity we assume that the sets of barbs is
        large enough to contain all barbs of the source terms, the target terms, and all barbs they
        might have in common.›

abbreviation hasBarbST
    :: "('procS, 'procT) Proc  'barbs  bool" ("_↓._" [70, 70] 80)
  where
  "P↓.a  (S. S ∈S P  S↓<SWB>a)  (T. T ∈T P  T↓<TWB>a)"

lemma STCalWB_hasBarbST:
  fixes P :: "('procS, 'procT) Proc"
    and a :: "'barbs"
  shows "P↓<STCalWB SWB TWB>a = P↓.a"
    by (simp add: STCalWB_def)

lemma preservation_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes preservation: "rel_preserves_barbs Rel (STCalWB SWB TWB)"
      and rel:          "(P, Q)  Rel"
      and barb:         "P↓.a"
  shows "Q↓.a"
      using preservation rel barb
    by (simp add: STCalWB_def)

lemma reflection_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes reflection: "rel_reflects_barbs Rel (STCalWB SWB TWB)"
      and rel:        "(P, Q)  Rel"
      and barb:       "Q↓.a"
  shows "P↓.a"
      using reflection rel barb
    by (simp add: STCalWB_def)

lemma respection_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes respection: "rel_respects_barbs Rel (STCalWB SWB TWB)"
      and rel:        "(P, Q)  Rel"
  shows "P↓.a = Q↓.a"
      using preservation_of_barbs_in_barbed_encoding[where Rel="Rel" and P="P" and Q="Q" and a="a"]
            reflection_of_barbs_in_barbed_encoding[where Rel="Rel" and P="P" and Q="Q" and a="a"]
            respection rel
    by blast

text ‹A term P of Proc reaches a barb a if either P is a source term that reaches a or P is a
        target term that reaches a.›

abbreviation reachesBarbST
    :: "('procS, 'procT) Proc  'barbs  bool" ("_⇓._" [70, 70] 80)
  where
  "P⇓.a  (S. S ∈S P  S⇓<SWB>a)  (T. T ∈T P  T⇓<TWB>a)"

lemma STCalWB_reachesBarbST:
  fixes P :: "('procS, 'procT) Proc"
    and a :: "'barbs"
  shows "P⇓<STCalWB SWB TWB>a = P⇓.a"
proof -
  have "S. SourceTerm S⇓<STCalWB SWB TWB>a = SourceTerm S⇓.a"
      using STCal_steps(1)
    by (auto simp add: STCalWB_def calS calT)
  moreover have "T. TargetTerm T⇓<STCalWB SWB TWB>a = TargetTerm T⇓.a"
      using STCal_steps(2)
    by (auto simp add: STCalWB_def calS calT)
  ultimately show "P⇓<STCalWB SWB TWB>a = P⇓.a"
    by (cases P, simp+)
qed

lemma weak_preservation_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes preservation: "rel_weakly_preserves_barbs Rel (STCalWB SWB TWB)"
      and rel:          "(P, Q)  Rel"
      and barb:         "P⇓.a"
  shows "Q⇓.a"
proof -
  from barb have "P⇓<STCalWB SWB TWB>a"
    by (simp add: STCalWB_reachesBarbST)
  with preservation rel have "Q⇓<STCalWB SWB TWB>a"
    by blast
  thus "Q⇓.a"
    by (simp add: STCalWB_reachesBarbST)
qed

lemma weak_reflection_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes reflection: "rel_weakly_reflects_barbs Rel (STCalWB SWB TWB)"
      and rel:        "(P, Q)  Rel"
      and barb:       "Q⇓.a"
  shows "P⇓.a"
proof -
  from barb have "Q⇓<STCalWB SWB TWB>a"
    by (simp add: STCalWB_reachesBarbST)
  with reflection rel have "P⇓<STCalWB SWB TWB>a"
    by blast
  thus "P⇓.a"
    by (simp add: STCalWB_reachesBarbST)
qed

lemma weak_respection_of_barbs_in_barbed_encoding:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and P Q :: "('procS, 'procT) Proc"
    and a   :: "'barbs"
  assumes respection: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
      and rel:        "(P, Q)  Rel"
  shows "P⇓.a = Q⇓.a"
proof (rule iffI)
  assume "P⇓.a"
  with respection rel show "Q⇓.a"
      using weak_preservation_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
next
  assume "Q⇓.a"
  with respection rel show "P⇓.a"
      using weak_reflection_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
qed

end

end

Theory SourceTargetRelation

theory SourceTargetRelation
  imports Encodings SimulationRelations
begin

section ‹Relation between Source and Target Terms›

subsection ‹Relations Induced by the Encoding Function›

text ‹We map encodability criteria on conditions of relations between source and target terms.
        The encoding function itself induces such relations. To analyse the preservation of source
        term behaviours we use relations that contain the pairs (S, enc S) for all source terms S.
›

inductive_set (in encoding) indRelR
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encR: "(SourceTerm S, TargetTerm (S))  indRelR"

abbreviation (in encoding) indRelRinfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧R _" [75, 75] 80)
  where
  "P ℛ⟦⋅⟧R Q  (P, Q)  indRelR"

inductive_set (in encoding) indRelRPO
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelRPO" |
  source: "(SourceTerm S, SourceTerm S)  indRelRPO" |
  target: "(TargetTerm T, TargetTerm T)  indRelRPO" |
  trans:  "(P, Q)  indRelRPO; (Q, R)  indRelRPO  (P, R)  indRelRPO"

abbreviation (in encoding) indRelRPOinfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ≲⟦⋅⟧R _" [75, 75] 80)
  where
  "P ≲⟦⋅⟧R Q  (P, Q)  indRelRPO"

lemma (in encoding) indRelRPO_refl:
  shows "refl indRelRPO"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧R P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    thus "P ≲⟦⋅⟧R P"
      by (simp add: indRelRPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    thus "P ≲⟦⋅⟧R P"
      by (simp add: indRelRPO.target)
  qed
qed

lemma (in encoding) indRelRPO_is_preorder:
  shows "preorder indRelRPO"
    unfolding preorder_on_def
proof
  show "refl indRelRPO"
    by (rule indRelRPO_refl)
next
  show "trans indRelRPO"
    unfolding trans_def
  proof clarify
    fix P Q R
    assume "P ≲⟦⋅⟧R Q" and "Q ≲⟦⋅⟧R R"
    thus "P ≲⟦⋅⟧R R"
      by (rule indRelRPO.trans)
  qed
qed

lemma (in encoding) refl_trans_closure_of_indRelR:
  shows "indRelRPO = indRelR*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧R Q"
  thus "(P, Q)  indRelR*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  indRelR*"
        using indRelR.encR[of S]
      by simp
  next
    case (source S)
    show "(SourceTerm S, SourceTerm S)  indRelR*"
      by simp
  next
    case (target T)
    show "(TargetTerm T, TargetTerm T)  indRelR*"
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  indRelR*" and "(Q, R)  indRelR*"
    thus "(P, R)  indRelR*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  indRelR*"
  thus "P ≲⟦⋅⟧R Q"
  proof induct
    show "P ≲⟦⋅⟧R P"
        using indRelRPO_refl
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧R Q"
    moreover assume "Q ℛ⟦⋅⟧R R"
    hence "Q ≲⟦⋅⟧R R"
      by (induct, simp add: indRelRPO.encR)
    ultimately show "P ≲⟦⋅⟧R R"
      by (rule indRelRPO.trans)
  qed
qed

text ‹The relation indRelR is the smallest relation that relates all source terms and their
        literal translations. Thus there exists a relation that relates source terms and their
        literal translations and satisfies some predicate on its pairs iff the predicate holds for
        the pairs of indRelR.›

lemma (in encoding) indRelR_impl_exists_source_target_relation:
  fixes PredA :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set  bool"
    and PredB :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "PredA indRelR  Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  PredA Rel"
    and "(P, Q)  indRelR. PredB (P, Q)
          Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. PredB (P, Q))"
proof -
  have A: "S. SourceTerm S ℛ⟦⋅⟧R TargetTerm (S)"
    by (simp add: indRelR.encR)
  thus "PredA indRelR  Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  PredA Rel"
    by blast
  with A show "(P, Q)  indRelR. PredB (P, Q)
    Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. PredB (P, Q))"
    by blast
qed

lemma (in encoding) source_target_relation_impl_indRelR:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes encRRel: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and condRel: "(P, Q)  Rel. Pred (P, Q)"
  shows "(P, Q)  indRelR. Pred (P, Q)"
proof clarify
  fix P Q
  assume "P ℛ⟦⋅⟧R Q"
  with encRRel have "(P, Q)  Rel"
    by (auto simp add: indRelR.simps)
  with condRel show "Pred (P, Q)"
    by simp
qed

lemma (in encoding) indRelR_iff_exists_source_target_relation:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "((P, Q)  indRelR. Pred (P, Q))
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q)))"
      using indRelR_impl_exists_source_target_relation(2)[where PredB="Pred"]
            source_target_relation_impl_indRelR[where Pred="Pred"]
    by blast

lemma (in encoding) indRelR_modulo_pred_impl_indRelRPO_modulo_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes reflCond:  "P. Pred (P, P)"
      and transCond: "P Q R. Pred (P, Q)  Pred (Q, R)  Pred (P, R)"
  shows "((P, Q)  indRelR. Pred (P, Q)) = ((P, Q)  indRelRPO. Pred (P, Q))"
proof auto
  fix P Q
  assume A: "x  indRelR. Pred x"
  assume "P ≲⟦⋅⟧R Q"
  thus "Pred (P, Q)"
  proof induct
    case (encR S)
    have "SourceTerm S ℛ⟦⋅⟧R TargetTerm (S)"
      by (simp add: indRelR.encR)
    with A show "Pred (SourceTerm S, TargetTerm (S))"
      by simp
  next
    case (source S)
    from reflCond show "Pred (SourceTerm S, SourceTerm S)"
      by simp
  next
    case (target T)
    from reflCond show "Pred (TargetTerm T, TargetTerm T)"
      by simp
  next
    case (trans P Q R)
    assume "Pred (P, Q)" and "Pred (Q, R)"
    with transCond show "Pred (P, R)"
      by blast
  qed
next
  fix P Q
  assume "x  indRelRPO. Pred x" and "P ℛ⟦⋅⟧R Q"
  thus "Pred (P, Q)"
    by (auto simp add: indRelRPO.encR indRelR.simps)
qed

lemma (in encoding) indRelRPO_iff_exists_source_target_relation:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "((P, Q)  indRelRPO. Pred (P, Q)) = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          ((P, Q)  Rel. Pred (P, Q))  preorder Rel)"
proof (rule iffI)
  have "S. SourceTerm S ≲⟦⋅⟧R TargetTerm (S)"
    by (simp add: indRelRPO.encR)
  moreover have "preorder indRelRPO"
      using indRelRPO_is_preorder
    by blast
  moreover assume "(P, Q)  indRelRPO. Pred (P, Q)"
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    ((P, Q)  Rel. Pred (P, Q))  preorder Rel"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           ((P, Q)  Rel. Pred (P, Q))  preorder Rel"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "(P, Q)  Rel. Pred (P, Q)" and A3: "preorder Rel"
    by blast
  show "(P, Q)  indRelRPO. Pred (P, Q)"
  proof clarify
    fix P Q
    assume "P ≲⟦⋅⟧R Q"
    hence "(P, Q)  Rel"
    proof induct
      case (encR S)
      from A1 show "(SourceTerm S, TargetTerm (S))  Rel"
        by simp
    next
      case (source S)
      from A3 show "(SourceTerm S, SourceTerm S)  Rel"
          unfolding preorder_on_def refl_on_def
        by simp
    next
      case (target T)
      from A3 show "(TargetTerm T, TargetTerm T)  Rel"
          unfolding preorder_on_def refl_on_def
        by simp
    next
      case (trans P Q R)
      assume "(P, Q)  Rel" and "(Q, R)  Rel"
      with A3 show "(P, R)  Rel"
          unfolding preorder_on_def trans_def
        by blast
    qed
    with A2 show "Pred (P, Q)"
      by simp
  qed
qed

text ‹An encoding preserves, reflects, or respects a predicate iff indRelR preserves, reflects,
        or respects this predicate.›

lemma (in encoding) enc_satisfies_pred_impl_indRelR_satisfies_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes encCond: "S. Pred (SourceTerm S, TargetTerm (S))"
  shows "(P, Q)  indRelR. Pred (P, Q)"
    by (auto simp add: encCond indRelR.simps)

lemma (in encoding) indRelR_satisfies_pred_impl_enc_satisfies_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes relCond: "(P, Q)  indRelR. Pred (P, Q)"
  shows "S. Pred (SourceTerm S, TargetTerm (S))"
      using relCond indRelR.encR
    by simp

lemma (in encoding) enc_satisfies_pred_iff_indRelR_satisfies_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "(S. Pred (SourceTerm S, TargetTerm (S))) = ((P, Q)  indRelR. Pred (P, Q))"
      using enc_satisfies_pred_impl_indRelR_satisfies_pred[where Pred="Pred"]
            indRelR_satisfies_pred_impl_enc_satisfies_pred[where Pred="Pred"]
    by blast

lemma (in encoding) enc_satisfies_binary_pred_iff_indRelR_satisfies_binary_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  'b  bool"
  shows "(S a. Pred (SourceTerm S, TargetTerm (S)) a) = ((P, Q)  indRelR. a. Pred (P, Q) a)"
      using enc_satisfies_pred_iff_indRelR_satisfies_pred
    by simp

lemma (in encoding) enc_preserves_pred_iff_indRelR_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_preserves_pred Pred = rel_preserves_pred indRelR Pred"
      using enc_satisfies_pred_iff_indRelR_satisfies_pred[where Pred="λ(P, Q). Pred P  Pred Q"]
    by blast

lemma (in encoding) enc_preserves_binary_pred_iff_indRelR_preserves_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_preserves_binary_pred Pred = rel_preserves_binary_pred indRelR Pred"
      using enc_satisfies_binary_pred_iff_indRelR_satisfies_binary_pred[where
             Pred="λ(P, Q) a. Pred P a  Pred Q a"]
    by blast

lemma (in encoding) enc_preserves_pred_iff_indRelRPO_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_preserves_pred Pred = rel_preserves_pred indRelRPO Pred"
      using enc_preserves_pred_iff_indRelR_preserves_pred[where Pred="Pred"]
            indRelR_modulo_pred_impl_indRelRPO_modulo_pred[where
             Pred="λ(P, Q). Pred P  Pred Q"]
    by blast

lemma (in encoding) enc_reflects_pred_iff_indRelR_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_reflects_pred Pred = rel_reflects_pred indRelR Pred"
      using enc_satisfies_pred_iff_indRelR_satisfies_pred[where Pred="λ(P, Q). Pred Q  Pred P"]
    by blast

lemma (in encoding) enc_reflects_binary_pred_iff_indRelR_reflects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_reflects_binary_pred Pred = rel_reflects_binary_pred indRelR Pred"
      using enc_satisfies_binary_pred_iff_indRelR_satisfies_binary_pred[where
             Pred="λ(P, Q) a. Pred Q a  Pred P a"]
    by blast

lemma (in encoding) enc_reflects_pred_iff_indRelRPO_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_reflects_pred Pred = rel_reflects_pred indRelRPO Pred"
      using enc_reflects_pred_iff_indRelR_reflects_pred[where Pred="Pred"]
            indRelR_modulo_pred_impl_indRelRPO_modulo_pred[where
             Pred="λ(P, Q). Pred Q  Pred P"]
    by blast

lemma (in encoding) enc_respects_pred_iff_indRelR_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred = rel_respects_pred indRelR Pred"
      using enc_preserves_pred_iff_indRelR_preserves_pred[where Pred="Pred"]
            enc_reflects_pred_iff_indRelR_reflects_pred[where Pred="Pred"]
    by blast

lemma (in encoding) enc_respects_binary_pred_iff_indRelR_respects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_respects_binary_pred Pred = rel_respects_binary_pred indRelR Pred"
      using enc_preserves_binary_pred_iff_indRelR_preserves_binary_pred[where Pred="Pred"]
            enc_reflects_binary_pred_iff_indRelR_reflects_binary_pred[where Pred="Pred"]
    by blast

lemma (in encoding) enc_respects_pred_iff_indRelRPO_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred = rel_respects_pred indRelRPO Pred"
      using enc_respects_pred_iff_indRelR_respects_pred[where Pred="Pred"]
            indRelR_modulo_pred_impl_indRelRPO_modulo_pred[where Pred="λ(P, Q). Pred Q = Pred P"]
    apply simp by blast

text ‹Accordingly an encoding preserves, reflects, or respects a predicate iff there exists a
        relation that relates source terms with their literal translations and preserves, reflects,
        or respects this predicate.›

lemma (in encoding) enc_satisfies_pred_iff_source_target_satisfies_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "(S. Pred (SourceTerm S, TargetTerm (S)))
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q)))"
    and "P Q R. Pred (P, Q)  Pred (Q, R)  Pred (P, R); P. Pred (P, P) 
         (S. Pred (SourceTerm S, TargetTerm (S))) = (Rel. (S.
         (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q))  preorder Rel)"
proof -
  show "(S. Pred (SourceTerm S, TargetTerm (S)))
        = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q)))"
      using enc_satisfies_pred_iff_indRelR_satisfies_pred[where Pred="Pred"]
            indRelR_iff_exists_source_target_relation[where Pred="Pred"]
    by simp
next
  have "(S. Pred (SourceTerm S, TargetTerm (S))) = ((P, Q)  indRelR. Pred (P, Q))"
      using enc_satisfies_pred_iff_indRelR_satisfies_pred[where Pred="Pred"]
    by simp
  moreover assume "P Q R. Pred (P, Q)  Pred (Q, R)  Pred (P, R)" and "P. Pred (P, P)"
  hence "((P, Q)  indRelR. Pred (P, Q)) = ((P, Q)  indRelRPO. Pred (P, Q))"
      using indRelR_modulo_pred_impl_indRelRPO_modulo_pred[where Pred="Pred"]
    by blast
  ultimately show "(S. Pred (SourceTerm S, TargetTerm (S))) = (Rel.
   (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q))  preorder Rel)"
      using indRelRPO_iff_exists_source_target_relation[where Pred="Pred"]
    by simp
qed

lemma (in encoding) enc_preserves_pred_iff_source_target_rel_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_preserves_pred Pred
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_pred Rel Pred)"
    and "enc_preserves_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_preserves_pred Rel Pred  preorder Rel)"
proof -
  have A1: "enc_preserves_pred Pred
            = (S. (λ(P, Q). Pred P  Pred Q) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover have A2: "Rel. rel_preserves_pred Rel Pred
                     = ((P, Q)  Rel. (λ(P, Q). Pred P  Pred Q) (P, Q))"
    by blast
  ultimately show "enc_preserves_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_preserves_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). Pred P  Pred Q"]
    by simp
  from A1 A2 show "enc_preserves_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_preserves_pred Rel Pred  preorder Rel)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(2)[where
             Pred="λ(P, Q). Pred P  Pred Q"]
    by simp
qed

lemma (in encoding) enc_preserves_binary_pred_iff_source_target_rel_preserves_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_preserves_binary_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_preserves_binary_pred Rel Pred)"
proof -
  have "enc_preserves_binary_pred Pred
        = (S. (λ(P, Q). a. Pred P a  Pred Q a) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover have "Rel. rel_preserves_binary_pred Rel Pred
                 = ((P, Q)  Rel. (λ(P, Q). a. Pred P a  Pred Q a) (P, Q))"
    by blast
  ultimately show "enc_preserves_binary_pred Pred = (Rel. (S.
                   (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_binary_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). a. Pred P a  Pred Q a"]
    by simp
qed

lemma (in encoding) enc_reflects_pred_iff_source_target_rel_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_reflects_pred Pred
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel Pred)"
    and "enc_reflects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_reflects_pred Rel Pred  preorder Rel)"
proof -
  have A1: "enc_reflects_pred Pred
        = (S. (λ(P, Q). Pred Q  Pred P) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover have A2: "Rel. rel_reflects_pred Rel Pred
                     = ((P, Q)  Rel. (λ(P, Q). Pred Q  Pred P) (P, Q))"
    by blast
  ultimately show "enc_reflects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_reflects_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). Pred Q  Pred P"]
    by simp
  from A1 A2 show "enc_reflects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_reflects_pred Rel Pred  preorder Rel)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(2)[where
             Pred="λ(P, Q). Pred Q  Pred P"]
    by simp
qed

lemma (in encoding) enc_reflects_binary_pred_iff_source_target_rel_reflects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_reflects_binary_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_reflects_binary_pred Rel Pred)"
proof -
  have "enc_reflects_binary_pred Pred
        = (S. (λ(P, Q). a. Pred Q a  Pred P a) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover have "Rel. rel_reflects_binary_pred Rel Pred
                 = ((P, Q)  Rel. (λ(P, Q). a. Pred Q a  Pred P a) (P, Q))"
    by blast
  ultimately show "enc_reflects_binary_pred Pred = (Rel. (S.
                   (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_binary_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). a. Pred Q a  Pred P a"]
    by simp
qed

lemma (in encoding) enc_respects_pred_iff_source_target_rel_respects_pred_encR:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred)"
    and "enc_respects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_respects_pred Rel Pred  preorder Rel)"
proof -
  have A1: "enc_respects_pred Pred
            = (S. (λ(P, Q). Pred P = Pred Q) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover
  have A2: "Rel. rel_respects_pred Rel Pred = ((P, Q)  Rel. (λ(P, Q). Pred P = Pred Q) (P, Q))"
    by blast
  ultimately show "enc_respects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_respects_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). Pred P = Pred Q"]
    by simp
  from A1 A2 show "enc_respects_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    rel_respects_pred Rel Pred  preorder Rel)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(2)[where
             Pred="λ(P, Q). Pred P = Pred Q"]
    by simp
qed

lemma (in encoding) enc_respects_binary_pred_iff_source_target_rel_respects_binary_pred_encR:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "enc_respects_binary_pred Pred = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_respects_binary_pred Rel Pred)"
proof -
  have "enc_respects_binary_pred Pred
        = (S. (λ(P, Q). a. Pred P a = Pred Q a) (SourceTerm S, TargetTerm (S)))"
    by blast
  moreover have "Rel. rel_respects_binary_pred Rel Pred
                 = ((P, Q)  Rel. (λ(P, Q). a. Pred P a = Pred Q a) (P, Q))"
    by blast
  ultimately show "enc_respects_binary_pred Pred = (Rel. (S.
                   (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred)"
      using enc_satisfies_pred_iff_source_target_satisfies_pred(1)[where
             Pred="λ(P, Q). a. Pred P a = Pred Q a"]
    by simp
qed

text ‹To analyse the reflection of source term behaviours we use relations that contain the pairs
        (enc S, S) for all source terms S.›

inductive_set (in encoding) indRelL
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encL: "(TargetTerm (S), SourceTerm S)  indRelL"

abbreviation (in encoding) indRelLinfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧L _" [75, 75] 80)
  where
  "P ℛ⟦⋅⟧L Q  (P, Q)  indRelL"

inductive_set (in encoding) indRelLPO
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encL:   "(TargetTerm (S), SourceTerm S)  indRelLPO" |
  source: "(SourceTerm S, SourceTerm S)  indRelLPO" |
  target: "(TargetTerm T, TargetTerm T)  indRelLPO" |
  trans:  "(P, Q)  indRelLPO; (Q, R)  indRelLPO  (P, R)  indRelLPO"

abbreviation (in encoding) indRelLPOinfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ≲⟦⋅⟧L _" [75, 75] 80)
  where
  "P ≲⟦⋅⟧L Q  (P, Q)  indRelLPO"

lemma (in encoding) indRelLPO_refl:
  shows "refl indRelLPO"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧L P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    thus "P ≲⟦⋅⟧L P"
      by (simp add: indRelLPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    thus "P ≲⟦⋅⟧L P"
      by (simp add: indRelLPO.target)
  qed
qed

lemma (in encoding) indRelLPO_is_preorder:
  shows "preorder indRelLPO"
    unfolding preorder_on_def
proof
  show "refl indRelLPO"
    by (rule indRelLPO_refl)
next
  show "trans indRelLPO"
    unfolding trans_def
  proof clarify
    fix P Q R
    assume "P ≲⟦⋅⟧L Q" and "Q ≲⟦⋅⟧L R"
    thus "P ≲⟦⋅⟧L R"
      by (rule indRelLPO.trans)
  qed
qed

lemma (in encoding) refl_trans_closure_of_indRelL:
  shows "indRelLPO = indRelL*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧L Q"
  thus "(P, Q)  indRelL*"
  proof induct
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  indRelL*"
        using indRelL.encL[of S]
      by simp
  next
    case (source S)
    show "(SourceTerm S, SourceTerm S)  indRelL*"
      by simp
  next
    case (target T)
    show "(TargetTerm T, TargetTerm T)  indRelL*"
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  indRelL*" and "(Q, R)  indRelL*"
    thus "(P, R)  indRelL*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  indRelL*"
  thus "P ≲⟦⋅⟧L Q"
  proof induct
    show "P ≲⟦⋅⟧L P"
        using indRelLPO_refl
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧L Q"
    moreover assume "Q ℛ⟦⋅⟧L R"
    hence "Q ≲⟦⋅⟧L R"
      by (induct, simp add: indRelLPO.encL)
    ultimately show "P ≲⟦⋅⟧L R"
      by (simp add: indRelLPO.trans[of P Q R])
  qed
qed

text ‹The relations indRelR and indRelL are dual. indRelR preserves some predicate iff indRelL
        reflects it. indRelR reflects some predicate iff indRelL reflects it. indRelR respects some
        predicate iff indRelL does.›

lemma (in encoding) indRelR_preserves_pred_iff_indRelL_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "rel_preserves_pred indRelR Pred = rel_reflects_pred indRelL Pred"
proof
  assume preservation: "rel_preserves_pred indRelR Pred"
  show "rel_reflects_pred indRelL Pred"
  proof clarify
    fix P Q
    assume "P ℛ⟦⋅⟧L Q"
    from this obtain S where "S ∈S Q" and "S ∈T P"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧R P"
      by (simp add: indRelR.encR)
    moreover assume "Pred Q"
    ultimately show "Pred P"
        using preservation
      by blast
  qed
next
  assume reflection: "rel_reflects_pred indRelL Pred"
  show "rel_preserves_pred indRelR Pred"
  proof clarify
    fix P Q
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧L P"
      by (simp add: indRelL.encL)
    moreover assume "Pred P"
    ultimately show "Pred Q"
        using reflection
      by blast
  qed
qed

lemma (in encoding) indRelR_preserves_binary_pred_iff_indRelL_reflects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "rel_preserves_binary_pred indRelR Pred = rel_reflects_binary_pred indRelL Pred"
proof
  assume preservation: "rel_preserves_binary_pred indRelR Pred"
  show "rel_reflects_binary_pred indRelL Pred"
  proof clarify
    fix P Q x
    assume "P ℛ⟦⋅⟧L Q"
    from this obtain S where "S ∈S Q" and "S ∈T P"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧R P"
      by (simp add: indRelR.encR)
    moreover assume "Pred Q x"
    ultimately show "Pred P x"
        using preservation
      by blast
  qed
next
  assume reflection: "rel_reflects_binary_pred indRelL Pred"
  show "rel_preserves_binary_pred indRelR Pred"
  proof clarify
    fix P Q x
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧L P"
      by (simp add: indRelL.encL)
    moreover assume "Pred P x"
    ultimately show "Pred Q x"
        using reflection
      by blast
  qed
qed

lemma (in encoding) indRelR_reflects_pred_iff_indRelL_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "rel_reflects_pred indRelR Pred = rel_preserves_pred indRelL Pred"
proof
  assume reflection: "rel_reflects_pred indRelR Pred"
  show "rel_preserves_pred indRelL Pred"
  proof clarify
    fix P Q
    assume "P ℛ⟦⋅⟧L Q"
    from this obtain S where "S ∈S Q" and "S ∈T P"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧R P"
      by (simp add: indRelR.encR)
    moreover assume "Pred P"
    ultimately show "Pred Q"
        using reflection
      by blast
  qed
next
  assume preservation: "rel_preserves_pred indRelL Pred"
  show "rel_reflects_pred indRelR Pred"
  proof clarify
    fix P Q
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧L P"
      by (simp add: indRelL.encL)
    moreover assume "Pred Q"
    ultimately show "Pred P"
        using preservation
      by blast
  qed
qed

lemma (in encoding) indRelR_reflects_binary_pred_iff_indRelL_preserves_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "rel_reflects_binary_pred indRelR Pred = rel_preserves_binary_pred indRelL Pred"
proof
  assume reflection: "rel_reflects_binary_pred indRelR Pred"
  show "rel_preserves_binary_pred indRelL Pred"
  proof clarify
    fix P Q x
    assume "P ℛ⟦⋅⟧L Q"
    from this obtain S where "S ∈S Q" and "S ∈T P"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧R P"
      by (simp add: indRelR.encR)
    moreover assume "Pred P x"
    ultimately show "Pred Q x"
        using reflection
      by blast
  qed
next
  assume preservation: "rel_preserves_binary_pred indRelL Pred"
  show "rel_reflects_binary_pred indRelR Pred"
  proof clarify
    fix P Q x
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "Q ℛ⟦⋅⟧L P"
      by (simp add: indRelL.encL)
    moreover assume "Pred Q x"
    ultimately show "Pred P x"
        using preservation
      by blast
  qed
qed

lemma (in encoding) indRelR_respects_pred_iff_indRelL_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "rel_respects_pred indRelR Pred = rel_respects_pred indRelL Pred"
      using indRelR_preserves_pred_iff_indRelL_reflects_pred[where Pred="Pred"]
            indRelR_reflects_pred_iff_indRelL_preserves_pred[where Pred="Pred"]
    by blast

lemma (in encoding) indRelR_respects_binary_pred_iff_indRelL_respects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc 'b  bool"
  shows "rel_respects_binary_pred indRelR Pred = rel_respects_binary_pred indRelL Pred"
      using indRelR_preserves_binary_pred_iff_indRelL_reflects_binary_pred[where Pred="Pred"]
            indRelR_reflects_binary_pred_iff_indRelL_preserves_binary_pred[where Pred="Pred"]
    by blast

lemma (in encoding) indRelR_cond_preservation_iff_indRelL_cond_reflection:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_pred Rel Pred"
  then obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                    and A2: "rel_preserves_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover from A2 have "rel_reflects_pred (Rel¯) Pred"
    by simp
  ultimately show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_pred Rel Pred"
  then obtain Rel where B1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                    and B2: "rel_reflects_pred Rel Pred"
    by blast
  from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel¯"
    by simp
  moreover from B2 have "rel_preserves_pred (Rel¯) Pred"
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRelR_cond_binary_preservation_iff_indRelL_cond_binary_reflection:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_binary_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)
             rel_reflects_binary_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_binary_pred Rel Pred"
  then obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                    and A2: "rel_preserves_binary_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover from A2 have "rel_reflects_binary_pred (Rel¯) Pred"
    by simp
  ultimately
  show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_binary_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_binary_pred Rel Pred"
  then obtain Rel where B1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                    and B2: "rel_reflects_binary_pred Rel Pred"
    by blast
  from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel¯"
    by simp
  moreover from B2 have "rel_preserves_binary_pred (Rel¯) Pred"
    by simp
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_preserves_binary_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRelR_cond_reflection_iff_indRelL_cond_preservation:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel Pred"
  then obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                    and A2: "rel_reflects_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover from A2 have "rel_preserves_pred (Rel¯) Pred"
    by blast
  ultimately
  show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_pred Rel Pred"
  then obtain Rel where B1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                    and B2: "rel_preserves_pred Rel Pred"
    by blast
  from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel¯"
    by simp
  moreover from B2 have "rel_reflects_pred (Rel¯) Pred"
    by simp
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRelR_cond_binary_reflection_iff_indRelL_cond_binary_preservation:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_binary_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)
             rel_preserves_binary_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_binary_pred Rel Pred"
  then obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                    and A2: "rel_reflects_binary_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover from A2 have "rel_preserves_binary_pred (Rel¯) Pred"
    by blast
  ultimately
  show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_binary_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_binary_pred Rel Pred"
  then obtain Rel where B1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                    and B2: "rel_preserves_binary_pred Rel Pred"
    by blast
  from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel¯"
    by simp
  moreover from B2 have "rel_reflects_binary_pred (Rel¯) Pred"
    by simp
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_binary_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRelR_cond_respection_iff_indRelL_cond_respection:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "rel_respects_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  {(a, b). (b, a)  Rel}"
    by simp
  moreover from A2 have "rel_respects_pred {(a, b). (b, a)  Rel} Pred"
    by blast
  ultimately show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_pred Rel Pred"
  from this obtain Rel where A1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                         and A2: "rel_respects_pred Rel Pred"
    by blast
  from A1 have "S. (SourceTerm S, TargetTerm (S))  {(a, b). (b, a)  Rel}"
    by simp
  moreover from A2 have "rel_respects_pred {(a, b). (b, a)  Rel} Pred"
    by blast
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRelR_cond_binary_respection_iff_indRelL_cond_binary_respection:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred)
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)
             rel_respects_binary_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "rel_respects_binary_pred Rel Pred"
    by blast
  from A1 have "S. (TargetTerm (S), SourceTerm S)  {(a, b). (b, a)  Rel}"
    by simp
  moreover from A2 have "rel_respects_binary_pred {(a, b). (b, a)  Rel} Pred"
    by blast
  ultimately
  show "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_binary_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_binary_pred Rel Pred"
  from this obtain Rel where A1: "S. (TargetTerm (S), SourceTerm S)  Rel"
                         and A2: "rel_respects_binary_pred Rel Pred"
    by blast
  from A1 have "S. (SourceTerm S, TargetTerm (S))  {(a, b). (b, a)  Rel}"
    by simp
  moreover from A2 have "rel_respects_binary_pred {(a, b). (b, a)  Rel} Pred"
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred"
    by blast
qed

text ‹An encoding preserves, reflects, or respects a predicate iff indRelL reflects, preserves,
        or respects this predicate.›

lemma (in encoding) enc_preserves_pred_iff_indRelL_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_preserves_pred Pred = rel_reflects_pred indRelL Pred"
      using enc_preserves_pred_iff_indRelR_preserves_pred[where Pred="Pred"]
            indRelR_preserves_pred_iff_indRelL_reflects_pred[where Pred="Pred"]
    by blast

lemma (in encoding) enc_reflects_pred_iff_indRelL_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_reflects_pred Pred = rel_preserves_pred indRelL Pred"
      using enc_reflects_pred_iff_indRelR_reflects_pred[where Pred="Pred"]
            indRelR_reflects_pred_iff_indRelL_preserves_pred[where Pred="Pred"]
    by blast

lemma (in encoding) enc_respects_pred_iff_indRelL_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred = rel_respects_pred indRelL Pred"
      using enc_preserves_pred_iff_indRelL_reflects_pred[where Pred="Pred"]
            enc_reflects_pred_iff_indRelL_preserves_pred[where Pred="Pred"]
    by blast

text ‹An encoding preserves, reflects, or respects a predicate iff there exists a relation,
        namely indRelL, that relates literal translations with their source terms and reflects,
        preserves, or respects this predicate.›

lemma (in encoding) enc_preserves_pred_iff_source_target_rel_reflects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_preserves_pred Pred
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_reflects_pred Rel Pred)"
      using enc_preserves_pred_iff_source_target_rel_preserves_pred[where Pred="Pred"]
            indRelR_cond_preservation_iff_indRelL_cond_reflection[where Pred="Pred"]
    by simp

lemma (in encoding) enc_reflects_pred_iff_source_target_rel_preserves_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_reflects_pred Pred
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_preserves_pred Rel Pred)"
      using enc_reflects_pred_iff_source_target_rel_reflects_pred[where Pred="Pred"]
            indRelR_cond_reflection_iff_indRelL_cond_preservation[where Pred="Pred"]
    by simp

lemma (in encoding) enc_respects_pred_iff_source_target_rel_respects_pred_encL:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_pred Rel Pred)"
      using enc_respects_pred_iff_source_target_rel_respects_pred_encR[where Pred="Pred"]
            indRelR_cond_respection_iff_indRelL_cond_respection[where Pred="Pred"]
    by simp

text ‹To analyse the respection of source term behaviours we use relations that contain both kind
        of pairs: (S, enc S) as well as (enc S, S) for all source terms S.›

inductive_set (in encoding) indRel
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encR: "(SourceTerm S, TargetTerm (S))  indRel" |
  encL: "(TargetTerm (S), SourceTerm S)  indRel"

abbreviation (in encoding) indRelInfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧ _" [75, 75] 80)
  where
  "P ℛ⟦⋅⟧ Q  (P, Q)  indRel"

lemma (in encoding) indRel_symm:
  shows "sym indRel"
      unfolding sym_def
    by (auto simp add: indRel.simps indRel.encR indRel.encL)

inductive_set (in encoding) indRelEQ
    :: "((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelEQ" |
  encL:   "(TargetTerm (S), SourceTerm S)  indRelEQ" |
  target: "(TargetTerm T, TargetTerm T)  indRelEQ" |
  trans:  "(P, Q)  indRelEQ; (Q, R)  indRelEQ  (P, R)  indRelEQ"

abbreviation (in encoding) indRelEQinfix ::
    "('procS, 'procT) Proc  ('procS, 'procT) Proc  bool" ("_ ∼⟦⋅⟧ _" [75, 75] 80)
  where
  "P ∼⟦⋅⟧ Q  (P, Q)  indRelEQ"

lemma (in encoding) indRelEQ_refl:
  shows "refl indRelEQ"
    unfolding refl_on_def
proof auto
  fix P
  show "P ∼⟦⋅⟧ P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    moreover have "SourceTerm SP ∼⟦⋅⟧ TargetTerm (SP)"
      by (rule indRelEQ.encR)
    moreover have "TargetTerm (SP) ∼⟦⋅⟧ SourceTerm SP"
      by (rule indRelEQ.encL)
    ultimately show "P ∼⟦⋅⟧ P"
      by (simp add: indRelEQ.trans[where P="SourceTerm SP" and Q="TargetTerm (SP)"])
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    thus "P ∼⟦⋅⟧ P"
      by (simp add: indRelEQ.target)
  qed
qed

lemma (in encoding) indRelEQ_is_preorder:
  shows "preorder indRelEQ"
    unfolding preorder_on_def
proof
  show "refl indRelEQ"
    by (rule indRelEQ_refl)
next
  show "trans indRelEQ"
    unfolding trans_def
  proof clarify
    fix P Q R
    assume "P ∼⟦⋅⟧ Q" and "Q ∼⟦⋅⟧ R"
    thus "P ∼⟦⋅⟧ R"
      by (rule indRelEQ.trans)
  qed
qed

lemma (in encoding) indRelEQ_symm:
  shows "sym indRelEQ"
    unfolding sym_def
proof clarify
  fix P Q
  assume "P ∼⟦⋅⟧ Q"
  thus "Q ∼⟦⋅⟧ P"
  proof induct
    case (encR S)
    show "TargetTerm (S) ∼⟦⋅⟧ SourceTerm S"
      by (rule indRelEQ.encL)
  next
    case (encL S)
    show "SourceTerm S ∼⟦⋅⟧ TargetTerm (S)"
      by (rule indRelEQ.encR)
  next
    case (target T)
    show "TargetTerm T ∼⟦⋅⟧ TargetTerm T"
      by (rule indRelEQ.target)
  next
    case (trans P Q R)
    assume "R ∼⟦⋅⟧ Q" and "Q ∼⟦⋅⟧ P"
    thus "R ∼⟦⋅⟧ P"
      by (rule indRelEQ.trans)
  qed
qed

lemma (in encoding) indRelEQ_is_equivalence:
  shows "equivalence indRelEQ"
      using indRelEQ_is_preorder indRelEQ_symm
      unfolding equiv_def preorder_on_def
    by blast

lemma (in encoding) refl_trans_closure_of_indRel:
  shows "indRelEQ = indRel*"
proof auto
  fix P Q
  assume "P ∼⟦⋅⟧ Q"
  thus "(P, Q)  indRel*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  indRel*"
        using indRel.encR[of S]
      by simp
  next
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  indRel*"
        using indRel.encL[of S]
      by simp
  next
    case (target T)
    show "(TargetTerm T, TargetTerm T)  indRel*"
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  indRel*" and "(Q, R)  indRel*"
    thus "(P, R)  indRel*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  indRel*"
  thus "P ∼⟦⋅⟧ Q"
  proof induct
    show "P ∼⟦⋅⟧ P"
        using indRelEQ_refl
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ∼⟦⋅⟧ Q"
    moreover assume "Q ℛ⟦⋅⟧ R"
    hence "Q ∼⟦⋅⟧ R"
      by (induct, simp_all add: indRelEQ.encR indRelEQ.encL)
    ultimately show "P ∼⟦⋅⟧ R"
      by (rule indRelEQ.trans)
  qed
qed

lemma (in encoding) refl_symm_trans_closure_of_indRel:
  shows "indRelEQ = (symcl (indRel=))+"
proof -
  have "(symcl (indRel=))+ = (symcl indRel)*"
    by (rule refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRel"])
  moreover have "symcl indRel = indRel"
    by (simp add: indRel_symm symm_closure_of_symm_rel[where Rel="indRel"])
  ultimately show "indRelEQ = (symcl (indRel=))+"
    by (simp add: refl_trans_closure_of_indRel)
qed

lemma (in encoding) symm_closure_of_indRelR:
  shows "indRel = symcl indRelR"
    and "indRelEQ = (symcl (indRelR=))+"
proof -
  show "indRel = symcl indRelR"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧ Q"
    thus "(P, Q)  symcl indRelR"
      by (induct, simp_all add: symcl_def indRelR.encR)
  next
    fix P Q
    assume "(P, Q)  symcl indRelR"
    thus "P ℛ⟦⋅⟧ Q"
      by (auto simp add: symcl_def indRelR.simps indRel.encR indRel.encL)
  qed
  thus "indRelEQ = (symcl (indRelR=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelR"]
            refl_trans_closure_of_indRel
    by simp
qed

lemma (in encoding) symm_closure_of_indRelL:
  shows "indRel = symcl indRelL"
    and "indRelEQ = (symcl (indRelL=))+"
proof -
  show "indRel = symcl indRelL"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧ Q"
    thus "(P, Q)  symcl indRelL"
     by (induct, simp_all add: symcl_def indRelL.encL)
  next
    fix P Q
    assume "(P, Q)  symcl indRelL"
    thus "P ℛ⟦⋅⟧ Q"
      by (auto simp add: symcl_def indRelL.simps indRel.encR indRel.encL)
  qed
  thus "indRelEQ = (symcl (indRelL=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelL"]
            refl_trans_closure_of_indRel
    by simp
qed

text ‹The relation indRel is a combination of indRelL and indRelR. indRel respects a predicate
        iff indRelR (or indRelL) respects it.›

lemma (in encoding) indRel_respects_pred_iff_indRelR_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "rel_respects_pred indRel Pred = rel_respects_pred indRelR Pred"
proof
  assume respection: "rel_respects_pred indRel Pred"
  show "rel_respects_pred indRelR Pred"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "P ℛ⟦⋅⟧ Q"
      by (simp add: indRel.encR)
    moreover assume "Pred P"
    ultimately show "Pred Q"
        using respection
      by blast
  next
    fix P Q
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "P ℛ⟦⋅⟧ Q"
      by (simp add: indRel.encR)
    moreover assume "Pred Q"
    ultimately show "Pred P"
        using respection
      by blast
  qed
next
  assume "rel_respects_pred indRelR Pred"
  thus "rel_respects_pred indRel Pred"
      using symm_closure_of_indRelR(1)
            respection_and_closures(2)[where Rel="indRelR" and Pred="Pred"]
    by blast
qed

lemma (in encoding) indRel_respects_binary_pred_iff_indRelR_respects_binary_pred:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "rel_respects_binary_pred indRel Pred = rel_respects_binary_pred indRelR Pred"
proof
  assume respection: "rel_respects_binary_pred indRel Pred"
  show "rel_respects_binary_pred indRelR Pred"
  proof auto
    fix P Q x
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "P ℛ⟦⋅⟧ Q"
      by (simp add: indRel.encR)
    moreover assume "Pred P x"
    ultimately show "Pred Q x"
        using respection
      by blast
  next
    fix P Q x
    assume "P ℛ⟦⋅⟧R Q"
    from this obtain S where "S ∈S P" and "S ∈T Q"
      by (induct, blast)
    hence "P ℛ⟦⋅⟧ Q"
      by (simp add: indRel.encR)
    moreover assume "Pred Q x"
    ultimately show "Pred P x"
        using respection
      by blast
  qed
next
  assume "rel_respects_binary_pred indRelR Pred"
  thus "rel_respects_binary_pred indRel Pred"
      using symm_closure_of_indRelR(1)
            respection_of_binary_predicates_and_closures(2)[where Rel="indRelR" and Pred="Pred"]
    by blast
qed

lemma (in encoding) indRel_cond_respection_iff_indRelR_cond_respection:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "(Rel.
          (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
           rel_respects_pred Rel Pred)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
           (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_pred Rel Pred"
  from this obtain Rel
    where "S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel"
    and "rel_respects_pred Rel Pred"
    by blast
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel Pred"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "rel_respects_pred Rel Pred"
    by blast
  from A1 have "S. (SourceTerm S, TargetTerm (S))  symcl Rel
                 (TargetTerm (S), SourceTerm S)  symcl Rel"
    by (simp add: symcl_def)
  moreover from A2 have "rel_respects_pred (symcl Rel) Pred"
      using respection_and_closures(2)[where Rel="Rel" and Pred="Pred"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
         rel_respects_pred Rel Pred"
    by blast
qed

lemma (in encoding) indRel_cond_binary_respection_iff_indRelR_cond_binary_respection:
  fixes Pred :: "('procS, 'procT) Proc  'b  bool"
  shows "(Rel.
          (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
           rel_respects_binary_pred Rel Pred)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_respects_binary_pred Rel Pred)"
proof
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
           (TargetTerm (S), SourceTerm S)  Rel)  rel_respects_binary_pred Rel Pred"
  from this obtain Rel
    where "S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel"
    and "rel_respects_binary_pred Rel Pred"
    by blast
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_binary_pred Rel Pred"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "rel_respects_binary_pred Rel Pred"
    by blast
  from A1 have "S. (SourceTerm S, TargetTerm (S))  symcl Rel
                 (TargetTerm (S), SourceTerm S)  symcl Rel"
    by (simp add: symcl_def)
  moreover from A2 have "rel_respects_binary_pred (symcl Rel) Pred"
      using respection_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="Pred"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
         rel_respects_binary_pred Rel Pred"
    by blast
qed

text ‹An encoding respects a predicate iff indRel respects this predicate.›

lemma (in encoding) enc_respects_pred_iff_indRel_respects_pred:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred = rel_respects_pred indRel Pred"
      using enc_respects_pred_iff_indRelR_respects_pred[where Pred="Pred"]
            indRel_respects_pred_iff_indRelR_respects_pred[where Pred="Pred"]
    by simp

text ‹An encoding respects a predicate iff there exists a relation, namely indRel, that relates
        source terms and their literal translations in both directions and respects this predicate.
›

lemma (in encoding) enc_respects_pred_iff_source_target_rel_respects_pred_encRL:
  fixes Pred :: "('procS, 'procT) Proc  bool"
  shows "enc_respects_pred Pred
         = (Rel.
            (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
             rel_respects_pred Rel Pred)"
      using enc_respects_pred_iff_source_target_rel_respects_pred_encR[where Pred="Pred"]
            indRel_cond_respection_iff_indRelR_cond_respection[where Pred="Pred"]
    by simp

subsection ‹Relations Induced by the Encoding and a Relation on Target Terms›

text ‹Some encodability like e.g. operational correspondence are defined w.r.t. a relation on
        target terms. To analyse such criteria we include the respective target term relation in
        the considered relation on the disjoint union of source and target terms.›

inductive_set (in encoding) indRelRT
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelRT TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelRT TRel"

abbreviation (in encoding) indRelRTinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ℛ⟦⋅⟧RT<_> _" [75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧RT<TRel> Q  (P, Q)  indRelRT TRel"

inductive_set (in encoding) indRelRTPO
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelRTPO TRel" |
  source: "(SourceTerm S, SourceTerm S)  indRelRTPO TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelRTPO TRel" |
  trans:  "(P, Q)  indRelRTPO TRel; (Q, R)  indRelRTPO TRel  (P, R)  indRelRTPO TRel"

abbreviation (in encoding) indRelRTPOinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ≲⟦⋅⟧RT<_> _" [75, 75, 75] 80)
  where
  "P ≲⟦⋅⟧RT<TRel> Q  (P, Q)  indRelRTPO TRel"

lemma (in encoding) indRelRTPO_refl:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "refl (indRelRTPO TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧RT<TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    thus "P ≲⟦⋅⟧RT<TRel> P"
      by (simp add: indRelRTPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with refl show "P ≲⟦⋅⟧RT<TRel> P"
        unfolding refl_on_def
      by (simp add: indRelRTPO.target)
  qed
qed

lemma (in encoding) refl_trans_closure_of_indRelRT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "indRelRTPO TRel = (indRelRT TRel)*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧RT<TRel> Q"
  thus "(P, Q)  (indRelRT TRel)*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (indRelRT TRel)*"
        using indRelRT.encR[of S TRel]
      by simp
  next
    case (source S)
    show "(SourceTerm S, SourceTerm S)  (indRelRT TRel)*"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelRT TRel)*"
        using indRelRT.target[of T1 T2 TRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelRT TRel)*" and "(Q, R)  (indRelRT TRel)*"
    thus "(P, R)  (indRelRT TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelRT TRel)*"
  thus "P ≲⟦⋅⟧RT<TRel> Q"
  proof induct
    from refl show "P ≲⟦⋅⟧RT<TRel> P"
        using indRelRTPO_refl[of TRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧RT<TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧RT<TRel> R"
    hence "Q ≲⟦⋅⟧RT<TRel> R"
      by (induct, simp_all add: indRelRTPO.encR indRelRTPO.target)
    ultimately show "P ≲⟦⋅⟧RT<TRel> R"
      by (rule indRelRTPO.trans)
  qed
qed

lemma (in encoding) indRelRTPO_is_preorder:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
  shows "preorder (indRelRTPO TRel)"
    unfolding preorder_on_def
proof
  from reflT show "refl (indRelRTPO TRel)"
    by (rule indRelRTPO_refl)
next
  show "trans (indRelRTPO TRel)"
    unfolding trans_def
  proof clarify
    fix P Q R
    assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q ≲⟦⋅⟧RT<TRel> R"
    thus "P ≲⟦⋅⟧RT<TRel> R"
        using indRelRTPO.trans
      by blast
  qed
qed

lemma (in encoding) transitive_closure_of_TRel_to_indRelRTPO:
  fixes TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  shows "(TP, TQ)  TRel+  TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
proof -
  assume "(TP, TQ)  TRel+"
  thus "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
  proof induct
    fix TQ
    assume "(TP, TQ)  TRel"
    thus "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
      by (rule indRelRTPO.target)
  next
    case (step TQ TR)
    assume "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
    moreover assume "(TQ, TR)  TRel"
    hence "TargetTerm TQ ≲⟦⋅⟧RT<TRel> TargetTerm TR"
      by (simp add: indRelRTPO.target)
    ultimately show "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TR"
      by (rule indRelRTPO.trans)
  qed
qed

text ‹The relation indRelRT is the smallest relation that relates all source terms and their
        literal translations and contains TRel. Thus there exists a relation that relates source
        terms and their literal translations and satisfies some predicate on its pairs iff the
        predicate holds for the pairs of indRelR.›

lemma (in encoding) indRelR_modulo_pred_impl_indRelRT_modulo_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "((P, Q)  indRelR. Pred (P, Q)) = (TRel. ((TP, TQ)  TRel.
         Pred (TargetTerm TP, TargetTerm TQ))  ((P, Q)  indRelRT TRel. Pred (P, Q)))"
proof (rule iffI)
  assume A: "(P, Q)  indRelR. Pred (P, Q)"
  show "TRel. ((TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ))
        = ((P, Q)  indRelRT TRel. Pred (P, Q))"
  proof (rule allI, rule iffI)
    fix TRel
    assume "(TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ)"
    with A show "(P, Q)  indRelRT TRel. Pred (P, Q)"
      by (auto simp add: indRelR.encR indRelRT.simps)
  next
    fix TRel
    assume "(P, Q)  indRelRT TRel. Pred (P, Q)"
    thus "(TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ)"
      by (auto simp add: indRelRT.target)
  qed
next
  assume "TRel. ((TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ))
           ((P, Q)  indRelRT TRel. Pred (P, Q))"
  hence B: "TRel. ((TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ))
             ((P, Q)  indRelRT TRel. Pred (P, Q))"
    by blast
  have "S. Pred (SourceTerm S, TargetTerm (S))"
      using B[of "{}"]
    by (simp add: indRelRT.simps)
  thus "(P, Q)  indRelR. Pred (P, Q)"
    by (auto simp add: indRelR.simps)
qed

lemma (in encoding) indRelRT_iff_exists_source_target_relation:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  shows "(TRel. ((TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ))
           ((P, Q)  indRelRT TRel. Pred (P, Q)))
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. Pred (P, Q)))"
      using indRelR_iff_exists_source_target_relation[where Pred="Pred"]
            indRelR_modulo_pred_impl_indRelRT_modulo_pred[where Pred="Pred"]
    by simp

lemma (in encoding) indRelRT_modulo_pred_impl_indRelRTPO_modulo_pred:
  fixes TRel :: "('procT × 'procT) set"
    and Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes reflCond:  "P. Pred (P, P)"
      and transCond: "P Q R. Pred (P, Q)  Pred (Q, R)  Pred (P, R)"
  shows "((P, Q)  indRelRT TRel. Pred (P, Q)) = ((P, Q)  indRelRTPO TRel. Pred (P, Q))"
proof auto
  fix P Q
  assume A: "x  indRelRT TRel. Pred x"
  assume "P ≲⟦⋅⟧RT<TRel> Q"
  thus "Pred (P, Q)"
  proof induct
    case (encR S)
    have "SourceTerm S ℛ⟦⋅⟧RT<TRel> TargetTerm (S)"
      by (simp add: indRelRT.encR)
    with A show "Pred (SourceTerm S, TargetTerm (S))"
      by simp
  next
    case (source S)
    from reflCond show "Pred (SourceTerm S, SourceTerm S)"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    hence "TargetTerm T1 ℛ⟦⋅⟧RT<TRel> TargetTerm T2"
      by (simp add: indRelRT.target)
    with A show "Pred (TargetTerm T1, TargetTerm T2)"
      by simp
  next
    case (trans P Q R)
    assume "Pred (P, Q)" and "Pred (Q, R)"
    with transCond show "Pred (P, R)"
      by blast
  qed
next
  fix P Q
  assume "x  indRelRTPO TRel. Pred x" and "P ℛ⟦⋅⟧RT<TRel> Q"
  thus "Pred (P, Q)"
    by (auto simp add: indRelRTPO.encR indRelRTPO.target indRelRT.simps)
qed

lemma (in encoding) indRelR_modulo_pred_impl_indRelRTPO_modulo_pred:
  fixes Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc)  bool"
  assumes "P. Pred (P, P)"
      and "P Q R. Pred (P, Q)  Pred (Q, R)  Pred (P, R)"
  shows "((P, Q)  indRelR. Pred (P, Q))
         = (TRel. ((TP, TQ)  TRel. Pred (TargetTerm TP, TargetTerm TQ))
             ((P, Q)  indRelRTPO TRel. Pred (P, Q)))"
proof -
  have "((P, Q)indRelR. Pred (P, Q)) = (TRel. ((TP, TQ)  TRel.
        Pred (TargetTerm TP, TargetTerm TQ))  ((P, Q)  indRelRT TRel. Pred (P, Q)))"
      using indRelR_modulo_pred_impl_indRelRT_modulo_pred[where Pred="Pred"]
    by simp
  moreover
  have "TRel. ((P, Q)indRelRT TRel. Pred (P, Q)) = ((P, Q)indRelRTPO TRel. Pred (P, Q))"
      using assms indRelRT_modulo_pred_impl_indRelRTPO_modulo_pred[where Pred="Pred"]
    by blast
  ultimately show ?thesis
    by simp
qed

text ‹The relation indRelLT includes TRel and relates literal translations and their source
        terms.›

inductive_set (in encoding) indRelLT
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encL:   "(TargetTerm (S), SourceTerm S)  indRelLT TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelLT TRel"

abbreviation (in encoding) indRelLTinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ℛ⟦⋅⟧LT<_> _" [75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧LT<TRel> Q  (P, Q)  indRelLT TRel"

inductive_set (in encoding) indRelLTPO
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encL:   "(TargetTerm (S), SourceTerm S)  indRelLTPO TRel" |
  source: "(SourceTerm S, SourceTerm S)  indRelLTPO TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelLTPO TRel" |
  trans:  "(P, Q)  indRelLTPO TRel; (Q, R)  indRelLTPO TRel  (P, R)  indRelLTPO TRel"

abbreviation (in encoding) indRelLTPOinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ≲⟦⋅⟧LT<_> _" [75, 75, 75] 80)
  where
  "P ≲⟦⋅⟧LT<TRel> Q  (P, Q)  indRelLTPO TRel"

lemma (in encoding) indRelLTPO_refl:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "refl (indRelLTPO TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧LT<TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    thus "P ≲⟦⋅⟧LT<TRel> P"
      by (simp add: indRelLTPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with refl show "P ≲⟦⋅⟧LT<TRel> P"
        using indRelLTPO.target[of TP TP TRel]
        unfolding refl_on_def
      by simp
  qed
qed

lemma (in encoding) refl_trans_closure_of_indRelLT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "indRelLTPO TRel = (indRelLT TRel)*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧LT<TRel> Q"
  thus "(P, Q)  (indRelLT TRel)*"
  proof induct
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (indRelLT TRel)*"
        using indRelLT.encL[of S TRel]
      by simp
  next
    case (source S)
    show "(SourceTerm S, SourceTerm S)  (indRelLT TRel)*"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelLT TRel)*"
        using indRelLT.target[of T1 T2 TRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelLT TRel)*" and "(Q, R)  (indRelLT TRel)*"
    thus "(P, R)  (indRelLT TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelLT TRel)*"
  thus "P ≲⟦⋅⟧LT<TRel> Q"
  proof induct
    from refl show "P ≲⟦⋅⟧LT<TRel> P"
        using indRelLTPO_refl[of TRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧LT<TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧LT<TRel> R"
    hence "Q ≲⟦⋅⟧LT<TRel> R"
      by (induct, simp_all add: indRelLTPO.encL indRelLTPO.target)
    ultimately show "P ≲⟦⋅⟧LT<TRel> R"
      by (rule indRelLTPO.trans)
  qed
qed

inductive_set (in encoding) indRelT
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelT TRel" |
  encL:   "(TargetTerm (S), SourceTerm S)  indRelT TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelT TRel"

abbreviation (in encoding) indRelTinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ℛ⟦⋅⟧T<_> _" [75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧T<TRel> Q  (P, Q)  indRelT TRel"

lemma (in encoding) indRelT_symm:
  fixes TRel :: "('procT × 'procT) set"
  assumes symm: "sym TRel"
  shows "sym (indRelT TRel)"
    unfolding sym_def
proof clarify
  fix P Q
  assume "(P, Q)  indRelT TRel"
  thus "(Q, P)  indRelT TRel"
      using symm
      unfolding sym_def
    by (induct, simp_all add: indRelT.encL indRelT.encR indRelT.target)
qed

inductive_set (in encoding) indRelTEQ
    :: "('procT × 'procT) set  ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelTEQ TRel" |
  encL:   "(TargetTerm (S), SourceTerm S)  indRelTEQ TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelTEQ TRel" |
  trans:  "(P, Q)  indRelTEQ TRel; (Q, R)  indRelTEQ TRel  (P, R)  indRelTEQ TRel"

abbreviation (in encoding) indRelTEQinfix
    :: "('procS, 'procT) Proc  ('procT × 'procT) set  ('procS, 'procT) Proc  bool"
       ("_ ∼⟦⋅⟧T<_> _" [75, 75, 75] 80)
  where
  "P ∼⟦⋅⟧T<TRel> Q  (P, Q)  indRelTEQ TRel"

lemma (in encoding) indRelTEQ_refl:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "refl (indRelTEQ TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ∼⟦⋅⟧T<TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    moreover have "SourceTerm SP ∼⟦⋅⟧T<TRel> TargetTerm (SP)"
      by (rule indRelTEQ.encR)
    moreover have "TargetTerm (SP) ∼⟦⋅⟧T<TRel> SourceTerm SP"
      by (rule indRelTEQ.encL)
    ultimately show "P ∼⟦⋅⟧T<TRel> P"
      by (simp add: indRelTEQ.trans[where P="SourceTerm SP" and Q="TargetTerm (SP)"])
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with refl show "P ∼⟦⋅⟧T<TRel> P"
        unfolding refl_on_def
      by (simp add: indRelTEQ.target)
  qed
qed

lemma (in encoding) indRelTEQ_symm:
  fixes TRel :: "('procT × 'procT) set"
  assumes symm: "sym TRel"
  shows "sym (indRelTEQ TRel)"
    unfolding sym_def
proof clarify
  fix P Q
  assume "P ∼⟦⋅⟧T<TRel> Q"
  thus "Q ∼⟦⋅⟧T<TRel> P"
  proof induct
    case (encR S)
    show "TargetTerm (S) ∼⟦⋅⟧T<TRel> SourceTerm S"
      by (rule indRelTEQ.encL)
  next
    case (encL S)
    show "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
      by (rule indRelTEQ.encR)
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    with symm show "TargetTerm T2 ∼⟦⋅⟧T<TRel> TargetTerm T1"
        unfolding sym_def
      by (simp add: indRelTEQ.target)
  next
    case (trans P Q R)
    assume "R ∼⟦⋅⟧T<TRel> Q" and "Q ∼⟦⋅⟧T<TRel> P"
    thus "R ∼⟦⋅⟧T<TRel> P"
      by (rule indRelTEQ.trans)
  qed
qed

lemma (in encoding) refl_trans_closure_of_indRelT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
  shows "indRelTEQ TRel = (indRelT TRel)*"
proof auto
  fix P Q
  assume "P ∼⟦⋅⟧T<TRel> Q"
  thus "(P, Q)  (indRelT TRel)*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (indRelT TRel)*"
        using indRelT.encR[of S TRel]
      by simp
  next
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (indRelT TRel)*"
        using indRelT.encL[of S TRel]
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelT TRel)*"
        using indRelT.target[of T1 T2 TRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelT TRel)*" and "(Q, R)  (indRelT TRel)*"
    thus "(P, R)  (indRelT TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelT TRel)*"
  thus "P ∼⟦⋅⟧T<TRel> Q"
  proof induct
    from refl show "P ∼⟦⋅⟧T<TRel> P"
        using indRelTEQ_refl[of TRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ∼⟦⋅⟧T<TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧T<TRel> R"
    hence "Q ∼⟦⋅⟧T<TRel> R"
      by (induct, simp_all add: indRelTEQ.encR indRelTEQ.encL indRelTEQ.target)
    ultimately show "P ∼⟦⋅⟧T<TRel> R"
      by (rule indRelTEQ.trans)
  qed
qed

lemma (in encoding) refl_symm_trans_closure_of_indRelT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
      and symm: "sym TRel"
  shows "indRelTEQ TRel = (symcl ((indRelT TRel)=))+"
proof -
  have "(symcl ((indRelT TRel)=))+ = (symcl (indRelT TRel))*"
    by (rule refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelT TRel"])
  moreover from symm have "symcl (indRelT TRel) = indRelT TRel"
      using indRelT_symm[where TRel="TRel"] symm_closure_of_symm_rel[where Rel="indRelT TRel"]
    by blast
  ultimately show "indRelTEQ TRel = (symcl ((indRelT TRel)=))+"
      using refl refl_trans_closure_of_indRelT[where TRel="TRel"]
    by simp
qed

lemma (in encoding) symm_closure_of_indRelRT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
      and symm: "sym TRel"
  shows "indRelT TRel = symcl (indRelRT TRel)"
    and "indRelTEQ TRel = (symcl ((indRelRT TRel)=))+"
proof -
  show "indRelT TRel = symcl (indRelRT TRel)"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧T<TRel> Q"
    thus "(P, Q)  symcl (indRelRT TRel)"
      by (induct, simp_all add: symcl_def indRelRT.encR indRelRT.target)
  next
    fix P Q
    assume "(P, Q)  symcl (indRelRT TRel)"
    thus "P ℛ⟦⋅⟧T<TRel> Q"
    proof (auto simp add: symcl_def indRelRT.simps)
      fix S
      show "SourceTerm S ℛ⟦⋅⟧T<TRel> TargetTerm (S)"
        by (rule indRelT.encR)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      thus "TargetTerm T1 ℛ⟦⋅⟧T<TRel> TargetTerm T2"
        by (rule indRelT.target)
    next
      fix S
      show "TargetTerm (S) ℛ⟦⋅⟧T<TRel> SourceTerm S"
        by (rule indRelT.encL)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      with symm show "TargetTerm T2 ℛ⟦⋅⟧T<TRel> TargetTerm T1"
          unfolding sym_def
        by (simp add: indRelT.target)
    qed
  qed
  with refl show "indRelTEQ TRel = (symcl ((indRelRT TRel)=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelRT TRel"]
            refl_trans_closure_of_indRelT
    by simp
qed

lemma (in encoding) symm_closure_of_indRelLT:
  fixes TRel :: "('procT × 'procT) set"
  assumes refl: "refl TRel"
      and symm: "sym TRel"
  shows "indRelT TRel = symcl (indRelLT TRel)"
    and "indRelTEQ TRel = (symcl ((indRelLT TRel)=))+"
proof -
  show "indRelT TRel = symcl (indRelLT TRel)"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧T<TRel> Q"
    thus "(P, Q)  symcl (indRelLT TRel)"
      by (induct, simp_all add: symcl_def indRelLT.encL indRelLT.target)
  next
    fix P Q
    assume "(P, Q)  symcl (indRelLT TRel)"
    thus "P ℛ⟦⋅⟧T<TRel> Q"
    proof (auto simp add: symcl_def indRelLT.simps)
      fix S
      show "SourceTerm S ℛ⟦⋅⟧T<TRel> TargetTerm (S)"
        by (rule indRelT.encR)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      thus "TargetTerm T1 ℛ⟦⋅⟧T<TRel> TargetTerm T2"
        by (rule indRelT.target)
    next
      fix S
      show "TargetTerm (S) ℛ⟦⋅⟧T<TRel> SourceTerm S"
        by (rule indRelT.encL)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      with symm show "TargetTerm T2 ℛ⟦⋅⟧T<TRel> TargetTerm T1"
          unfolding sym_def
        by (simp add: indRelT.target)
    qed
  qed
  with refl show "indRelTEQ TRel = (symcl ((indRelLT TRel)=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelLT TRel"]
            refl_trans_closure_of_indRelT
    by simp
qed

text ‹If the relations indRelRT, indRelLT, or indRelT contain a pair of target terms, then this
        pair is also related by the considered target term relation.›

lemma (in encoding) indRelRT_to_TRel:
  fixes TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧RT<TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelRT.simps)

lemma (in encoding) indRelLT_to_TRel:
  fixes TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧LT<TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelLT.simps)

lemma (in encoding) indRelT_to_TRel:
  fixes TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧T<TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelT.simps)

text ‹If the preorders indRelRTPO, indRelLTPO, or the equivalence indRelTEQ contain a pair of
        terms, then the pair of target terms that is related to these two terms is also related by
        the reflexive and transitive closure of the considered target term relation.›

lemma (in encoding) indRelRTPO_to_TRel:
  fixes TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel: "P ≲⟦⋅⟧RT<TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
    and "SP TQ. SP ∈S P  TQ ∈T Q
          (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    and "TP SQ. TP ∈T P  SQ ∈S Q  False"
    and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
proof -
  have reflTRel: "S. (S, S)  TRel  {(T1, T2). S. T1 = S  T2 = S}"
    by auto
  from rel show "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
            and "SP TQ. SP ∈S P  TQ ∈T Q
                  (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            and "TP SQ. TP ∈T P  SQ ∈S Q  False"
            and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
  proof induct
    case (encR S)
    show "SP SQ. SP ∈S SourceTerm S  SQ ∈S TargetTerm (S)  SP = SQ"
     and "TP SQ. TP ∈T SourceTerm S  SQ ∈S TargetTerm (S)  False"
     and "TP TQ. TP ∈T SourceTerm S  TQ ∈T TargetTerm (S)  (TP, TQ)  TRel+"
      by simp_all
    from reflTRel show "SP TQ. SP ∈S SourceTerm S  TQ ∈T TargetTerm (S)
                         (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by blast
  next
    case (source S)
    show "SP SQ. SP ∈S SourceTerm S  SQ ∈S SourceTerm S  SP = SQ"
      by simp
    show "SP TQ. SP ∈S SourceTerm S  TQ ∈T SourceTerm S
           (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP SQ. TP ∈T SourceTerm S  SQ ∈S SourceTerm S  False"
     and "TP TQ. TP ∈T SourceTerm S  TQ ∈T SourceTerm S  (TP, TQ)  TRel+"
      by simp_all
  next
    case (target T1 T2)
    show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  SP = SQ"
     and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2
           (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2  False"
      by simp_all
    assume "(T1, T2)  TRel"
    thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2  (TP, TQ)  TRel+"
      by simp
  next
    case (trans P Q R)
    assume A1: "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
       and A2: "SP TQ. SP ∈S P  TQ ∈T Q
                 (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A3: "TP SQ. TP ∈T P  SQ ∈S Q  False"
       and A4: "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
       and A5: "SQ SR. SQ ∈S Q  SR ∈S R  SQ = SR"
       and A6: "SQ TR. SQ ∈S Q  TR ∈T R
                 (SQ, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A7: "TQ SR. TQ ∈T Q  SR ∈S R  False"
       and A8: "TQ TR. TQ ∈T Q  TR ∈T R  (TQ, TR)  TRel+"
    show "SP SR. SP ∈S P  SR ∈S R  SP = SR"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A1 A5 show "SP SR. SP ∈S P  SR ∈S R  SP = SR"
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A7 show ?thesis
        by blast
    qed
    show "SP TR. SP ∈S P  TR ∈T R
           (SP, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A1 A6 show ?thesis
        by blast
    next
      case (TargetTerm TQ)
      assume A9: "TQ ∈T Q"
      show "SP TR. SP ∈S P  TR ∈T R
             (SP, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      proof clarify
        fix SP TR
        assume "SP ∈S P"
        with A2 A9 have "(SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          by simp
        moreover assume "TR ∈T R"
        with A8 A9 have "(TQ, TR)  TRel+"
          by simp
        hence "(TQ, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
        proof induct
          fix T2
          assume "(TQ, T2)  TRel"
          thus "(TQ, T2)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by blast
        next
          case (step T2 T3)
          assume "(TQ, T2)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          moreover assume "(T2, T3)  TRel"
          hence "(T2, T3)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by blast
          ultimately show "(TQ, T3)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by simp
        qed
        ultimately show "(SP, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          by simp
      qed
    qed
    show "TP SR. TP ∈T P  SR ∈S R  False"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 show ?thesis
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A7 show ?thesis
        by blast
    qed
    show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 show ?thesis
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A4 A8 show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
        by auto
    qed
  qed
qed

lemma (in encoding) indRelLTPO_to_TRel:
  fixes TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel: "P ≲⟦⋅⟧LT<TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
    and "SP TQ. SP ∈S P  TQ ∈T Q  False"
    and "TP SQ. TP ∈T P  SQ ∈S Q
          (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
proof -
  have reflTRel: "S. (S, S)  TRel  {(T1, T2). S. T1 = S  T2 = S}"
    by auto
  from rel show "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
            and "SP TQ. SP ∈S P  TQ ∈T Q  False"
            and "TP SQ. TP ∈T P  SQ ∈S Q
                  (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
  proof induct
    case (encL S)
    show "SP SQ. SP ∈S TargetTerm (S)  SQ ∈S SourceTerm S   SP = SQ"
     and "SP TQ. SP ∈S TargetTerm (S)  TQ ∈T SourceTerm S  False"
     and "TP TQ. TP ∈T TargetTerm (S)  TQ ∈T SourceTerm S  (TP, TQ)  TRel+"
      by simp_all
    from reflTRel show "TP SQ. TP ∈T TargetTerm (S)  SQ ∈S SourceTerm S
                         (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by blast
  next
    case (source S)
    show "SP SQ. SP ∈S SourceTerm S  SQ ∈S SourceTerm S  SP = SQ"
      by simp
    show "SP TQ. SP ∈S SourceTerm S  TQ ∈T SourceTerm S  False"
     and "TP SQ. TP ∈T SourceTerm S  SQ ∈S SourceTerm S
           (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP TQ. TP ∈T SourceTerm S  TQ ∈T SourceTerm S  (TP, TQ)  TRel+"
      by simp_all
  next
    case (target T1 T2)
    show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  SP = SQ"
     and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2  False"
     and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2
           (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by simp_all
    assume "(T1, T2)  TRel"
    thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2  (TP, TQ)  TRel+"
      by simp
  next
    case (trans P Q R)
    assume A1: "SP SQ. SP ∈S P  SQ ∈S Q  SP = SQ"
       and A2: "SP TQ. SP ∈S P  TQ ∈T Q  False"
       and A3: "TP SQ. TP ∈T P  SQ ∈S Q
                 (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A4: "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
       and A5: "SQ SR. SQ ∈S Q  SR ∈S R  SQ = SR"
       and A6: "SQ TR. SQ ∈S Q  TR ∈T R  False"
       and A7: "TQ SR. TQ ∈T Q  SR ∈S R
                 (TQ, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A8: "TQ TR. TQ ∈T Q  TR ∈T R  (TQ, TR)  TRel+"
    show "SP SR. SP ∈S P  SR ∈S R  SP = SR"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A1 A5 show "SP SR. SP ∈S P  SR ∈S R  SP = SR"
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 show ?thesis
        by blast
    qed
    show "SP TR. SP ∈S P  TR ∈T R  False"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A6 show ?thesis
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 show ?thesis
        by blast
    qed
    show "TP SR. TP ∈T P  SR ∈S R
           (TP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 A5 show "TP SR. TP ∈T P  SR ∈S R
                        (TP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
        by blast
    next
      case (TargetTerm TQ)
      assume A9: "TQ ∈T Q"
      show "TP SR. TP ∈T P  SR ∈S R
             (TP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      proof clarify
        fix TP SR
        assume "TP ∈T P"
        with A4 A9 have "(TP, TQ)  TRel+"
          by simp
        hence "(TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
        proof induct
          fix T2
          assume "(TP, T2)  TRel"
          thus "(TP, T2)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by blast
        next
          case (step T2 T3)
          assume "(TP, T2)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          moreover assume "(T2, T3)  TRel"
          hence "(T2, T3)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by blast
          ultimately show "(TP, T3)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            by simp
        qed
        moreover assume "SR ∈S R"
        with A7 A9 have "(TQ, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          by simp
        ultimately show "(TP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
          by simp
      qed
    qed
    show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A6 show ?thesis
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A4 A8 show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
        by auto
    qed
  qed
qed

lemma (in encoding) indRelTEQ_to_TRel:
  fixes TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel: "P ∼⟦⋅⟧T<TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q
          (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    and "SP TQ. SP ∈S P  TQ ∈T Q
          (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    and "TP SQ. TP ∈T P  SQ ∈S Q
          (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    and "TP TQ. TP ∈T P  TQ ∈T Q
          (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
proof -
  have reflTRel: "S. (S, S)  TRel  {(T1, T2). S. T1 = S  T2 = S}"
    by auto
  from rel show "SP SQ. SP ∈S P  SQ ∈S Q
                  (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            and "SP TQ. SP ∈S P  TQ ∈T Q
                  (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            and "TP SQ. TP ∈T P  SQ ∈S Q
                  (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
            and "TP TQ. TP ∈T P  TQ ∈T Q
                  (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
  proof induct
    case (encR S)
    show "SP SQ. SP ∈S SourceTerm S  SQ ∈S TargetTerm (S)
           (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP SQ. TP ∈T SourceTerm S  SQ ∈S TargetTerm (S)
           (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP TQ. TP ∈T SourceTerm S  TQ ∈T TargetTerm (S)
           (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by simp+
    from reflTRel show "SP TQ. SP ∈S SourceTerm S  TQ ∈T TargetTerm (S)
                         (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by blast
  next
    case (encL S)
    show "SP SQ. SP ∈S TargetTerm (S)  SQ ∈S SourceTerm S
           (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "SP TQ. SP ∈S TargetTerm (S)  TQ ∈T SourceTerm S
           (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP TQ. TP ∈T TargetTerm (S)  TQ ∈T SourceTerm S
           (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by simp+
    from reflTRel show "TP SQ. TP ∈T TargetTerm (S)  SQ ∈S SourceTerm S
                         (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by blast
  next
    case (target T1 T2)
    show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2
           (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2
           (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
     and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2
           (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by simp+
    assume "(T1, T2)  TRel"
    thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2
           (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
      by blast
  next
    case (trans P Q R)
    assume A1: "SP SQ. SP ∈S P  SQ ∈S Q
                 (SP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A2: "SP TQ. SP ∈S P  TQ ∈T Q
                 (SP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A3: "TP SQ. TP ∈T P  SQ ∈S Q
                 (TP, SQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A4: "TP TQ. TP ∈T P  TQ ∈T Q
                 (TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A5: "SQ SR. SQ ∈S Q  SR ∈S R
                 (SQ, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A6: "SQ TR. SQ ∈S Q  TR ∈T R
                 (SQ, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A7: "TQ SR. TQ ∈T Q  SR ∈S R
                 (TQ, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
       and A8: "TQ TR. TQ ∈T Q  TR ∈T R
                 (TQ, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    show "SP SR. SP ∈S P  SR ∈S R
           (SP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A1 A5 show ?thesis
        by auto
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 A7 show ?thesis
        by auto
    qed
    show "SP TR. SP ∈S P  TR ∈T R  (SP, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A1 A6 show ?thesis
        by auto
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 A8 show ?thesis
        by auto
    qed
    show "TP SR. TP ∈T P  SR ∈S R  (TP, SR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 A5 show ?thesis
        by auto
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A4 A7 show ?thesis
        by auto
    qed
    show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 A6 show ?thesis
        by auto
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A4 A8 show ?thesis
        by auto
    qed
  qed
qed

lemma (in encoding) trans_closure_of_TRel_refl_cond:
  fixes TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes "(TP, TQ)  (TRel  {(T1, T2). S. T1 = S  T2 = S})+"
  shows "(TP, TQ)  TRel*"
    using assms
proof induct
  fix TQ
  assume "(TP, TQ)  TRel  {(T1, T2). S. T1 = S  T2 = S}"
  thus "(TP, TQ)  TRel*"
    by auto
next
  case (step TQ TR)
  assume "(TP, TQ)  TRel*"
  moreover assume "(TQ, TR)  TRel  {(T1, T2). S. T1 = S  T2 = S}"
  hence "(TQ, TR)  TRel*"
    by blast
  ultimately show "(TP, TR)  TRel*"
    by simp
qed

text ‹Note that if indRelRTPO relates a source term S to a target term T, then the translation of
        S is equal to T or indRelRTPO also relates the translation of S to T.›

lemma (in encoding) indRelRTPO_relates_source_target:
  fixes TRel :: "('procT × 'procT) set"
    and S    :: "'procS"
    and T    :: "'procT"
  assumes pair: "SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T"
  shows "(TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
proof -
  from pair have "(S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  hence "S = T  (S, T)  TRel+"
      using rtrancl_eq_or_trancl[of "S" T TRel]
    by blast
  moreover have "S = T  (TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
    by simp
  moreover
  have "(S, T)  TRel+  (TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
      using transitive_closure_of_TRel_to_indRelRTPO[where TRel="TRel"]
    by simp
  ultimately show "(TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
    by blast
qed

text ‹If indRelRTPO, indRelLTPO, or indRelTPO preserves barbs then so does the corresponding
        target term relation.›

lemma (in encoding_wrt_barbs) rel_with_target_impl_TRel_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes preservation: "rel_preserves_barbs Rel (STCalWB SWB TWB)"
      and targetInRel:  "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
  shows "rel_preserves_barbs TRel TWB"
proof clarify
  fix TP TQ a
  assume "(TP, TQ)  TRel"
  with targetInRel have "(TargetTerm TP, TargetTerm TQ)  Rel"
    by blast
  moreover assume "TP↓<TWB>a"
  hence "TargetTerm TP↓.a"
    by simp
  ultimately have "TargetTerm TQ↓.a"
      using preservation preservation_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "TQ↓<TWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs TRel TWB"
      using preservation
            rel_with_target_impl_TRel_preserves_barbs[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by (simp add: indRelRTPO.target)

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs TRel TWB"
      using preservation
            rel_with_target_impl_TRel_preserves_barbs[where Rel="indRelLTPO TRel" and TRel="TRel"]
    by (simp add: indRelLTPO.target)

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs TRel TWB"
      using preservation
            rel_with_target_impl_TRel_preserves_barbs[where Rel="indRelTEQ TRel" and TRel="TRel"]
    by (simp add: indRelTEQ.target)

lemma (in encoding_wrt_barbs) rel_with_target_impl_TRel_weakly_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes preservation: "rel_weakly_preserves_barbs Rel (STCalWB SWB TWB)"
      and targetInRel:  "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
  shows "rel_weakly_preserves_barbs TRel TWB"
proof clarify
  fix TP TQ a TP'
  assume "(TP, TQ)  TRel"
  with targetInRel have "(TargetTerm TP, TargetTerm TQ)  Rel"
    by blast
  moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>a"
  hence "TargetTerm TP⇓.a"
    by blast
  ultimately have "TargetTerm TQ⇓.a"
      using preservation weak_preservation_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "TQ⇓<TWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_weakly_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelRTPO TRel" and TRel="TRel"]
    by (simp add: indRelRTPO.target)

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_weakly_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelLTPO TRel" and TRel="TRel"]
    by (simp add: indRelLTPO.target)

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_weakly_preserves_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelTEQ TRel" and TRel="TRel"]
    by (simp add: indRelTEQ.target)

text ‹If indRelRTPO, indRelLTPO, or indRelTPO reflects barbs then so does the corresponding
        target term relation.›

lemma (in encoding_wrt_barbs) rel_with_target_impl_TRel_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes reflection: "rel_reflects_barbs Rel (STCalWB SWB TWB)"
      and targetInRel:  "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
  shows "rel_reflects_barbs TRel TWB"
proof clarify
  fix TP TQ a
  assume "(TP, TQ)  TRel"
  with targetInRel have "(TargetTerm TP, TargetTerm TQ)  Rel"
    by blast
  moreover assume "TQ↓<TWB>a"
  hence "TargetTerm TQ↓.a"
    by simp
  ultimately have "TargetTerm TP↓.a"
      using reflection reflection_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "TP↓<TWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs TRel TWB"
      using reflection
            rel_with_target_impl_TRel_reflects_barbs[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by (simp add: indRelRTPO.target)

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs TRel TWB"
      using reflection
            rel_with_target_impl_TRel_reflects_barbs[where Rel="indRelLTPO TRel" and TRel="TRel"]
    by (simp add: indRelLTPO.target)

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs TRel TWB"
      using reflection
            rel_with_target_impl_TRel_reflects_barbs[where Rel="indRelTEQ TRel" and TRel="TRel"]
    by (simp add: indRelTEQ.target)

lemma (in encoding_wrt_barbs) rel_with_target_impl_TRel_weakly_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes reflection: "rel_weakly_reflects_barbs Rel (STCalWB SWB TWB)"
      and targetInRel:  "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
  shows "rel_weakly_reflects_barbs TRel TWB"
proof clarify
  fix TP TQ a TQ'
  assume "(TP, TQ)  TRel"
  with targetInRel have "(TargetTerm TP, TargetTerm TQ)  Rel"
    by blast
  moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>a"
  hence "TargetTerm TQ⇓.a"
    by blast
  ultimately have "TargetTerm TP⇓.a"
      using reflection weak_reflection_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "TP⇓<TWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_weakly_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                        Rel="indRelRTPO TRel" and TRel="TRel"]
    by (simp add: indRelRTPO.target)

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_weakly_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                        Rel="indRelLTPO TRel" and TRel="TRel"]
    by (simp add: indRelLTPO.target)

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_weakly_reflects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                        Rel="indRelTEQ TRel" and TRel="TRel"]
    by (simp add: indRelTEQ.target)

text ‹If indRelRTPO, indRelLTPO, or indRelTPO respects barbs then so does the corresponding
        target term relation.›

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs TRel TWB"
      using respection indRelRTPO_impl_TRel_preserves_barbs[where TRel="TRel"]
            indRelRTPO_impl_TRel_reflects_barbs[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs TRel TWB"
      using respection indRelLTPO_impl_TRel_preserves_barbs[where TRel="TRel"]
            indRelLTPO_impl_TRel_reflects_barbs[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs TRel TWB"
      using respection indRelTEQ_impl_TRel_preserves_barbs[where TRel="TRel"]
            indRelTEQ_impl_TRel_reflects_barbs[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_weakly_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs TRel TWB"
      using respection indRelRTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            indRelRTPO_impl_TRel_weakly_reflects_barbs[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_weakly_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs TRel TWB"
      using respection indRelLTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            indRelLTPO_impl_TRel_weakly_reflects_barbs[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_weakly_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs TRel TWB"
      using respection indRelTEQ_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            indRelTEQ_impl_TRel_weakly_reflects_barbs[where TRel="TRel"]
    by blast

text ‹If indRelRTPO, indRelLTPO, or indRelTEQ is a simulation then so is the corresponding target
        term relation.›

lemma (in encoding) rel_with_target_impl_transC_TRel_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "weak_reduction_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "weak_reduction_simulation (TRel+) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel+" and "TP Target* TP'"
  thus "TQ'. TQ Target* TQ'  (TP', TQ')  TRel+"
  proof (induct arbitrary: TP')
    fix TQ TP'
    assume "(TP, TQ)  TRel"
    with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP Target* TP'"
    hence "TargetTerm TP (STCal Source Target)* (TargetTerm TP')"
      by (simp add: STCal_steps)
    ultimately obtain Q' where A2: "TargetTerm TQ (STCal Source Target)* Q'"
                           and A3: "(TargetTerm TP', Q')  Rel"
        using sim
      by blast
    from A2 obtain TQ' where A4: "TQ Target* TQ'" and A5: "TQ' ∈T Q'"
      by (auto simp add: STCal_steps)
    from A3 A5 trel have "(TP', TQ')  TRel+"
      by simp
    with A4 show "TQ'. TQ Target* TQ'  (TP', TQ')  TRel+"
      by blast
  next
    case (step TQ TR)
    assume "TP Target* TP'"
       and "TP'. TP Target* TP'  TQ'. TQ Target* TQ'  (TP', TQ')  TRel+"
    from this obtain TQ' where B1: "TQ Target* TQ'" and B2: "(TP', TQ')  TRel+"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
      by (simp add: STCal_steps)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target)* R'"
                           and B4: "(TargetTerm TQ', R')  Rel"
        using sim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target* TR'"
      by (auto simp add: STCal_steps)
    from B4 B5 trel have "(TQ', TR')  TRel+"
      by simp
    with B2 have "(TP', TR')  TRel+"
      by simp
    with B6 show "TR'. TR Target* TR'  (TP', TR')  TRel+"
      by blast
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  shows "weak_reduction_simulation (TRel+) Target"
      using sim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_simulation[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_reduction_simulation (indRelLTPO TRel) (STCal Source Target)"
  shows "weak_reduction_simulation (TRel+) Target"
      using sim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_simulation[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_transC_TRel_is_weak_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "weak_reduction_simulation (Rel¯) (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "weak_reduction_simulation ((TRel+)¯) Target"
proof clarify
  fix TP TQ TP'
  assume "(TQ, TP)  TRel+"
  moreover assume "TP Target* TP'"
  ultimately show "TQ'. TQ Target* TQ'  (TP', TQ')  (TRel+)¯"
  proof (induct arbitrary: TP')
    fix TP TP'
    assume "(TQ, TP)  TRel"
    with target have "(TargetTerm TP, TargetTerm TQ)  Rel¯"
      by simp
    moreover assume "TP Target* TP'"
    hence "TargetTerm TP (STCal Source Target)* (TargetTerm TP')"
      by (simp add: STCal_steps)
    ultimately obtain Q' where A2: "TargetTerm TQ (STCal Source Target)* Q'"
                           and A3: "(TargetTerm TP', Q')  Rel¯"
        using sim
      by blast
    from A2 obtain TQ' where A4: "TQ Target* TQ'" and A5: "TQ' ∈T Q'"
      by (auto simp add: STCal_steps(2))
    from A3 A5 trel have "(TP', TQ')  (TRel+)¯"
      by simp
    with A4 show "TQ'. TQ Target* TQ'  (TP', TQ')  (TRel+)¯"
      by blast
  next
    case (step TR TP TP')
    assume "TP Target* TP'"
    hence "TargetTerm TP (STCal Source Target)* (TargetTerm TP')"
      by (simp add: STCal_steps)
    moreover assume "(TR, TP)  TRel"
    with target have "(TargetTerm TP, TargetTerm TR)  Rel¯"
      by simp
    ultimately obtain R' where B1: "TargetTerm TR (STCal Source Target)* R'"
                           and B2: "(TargetTerm TP', R')  Rel¯"
        using sim
      by blast
    from B1 obtain TR' where B3: "TR' ∈T R'" and B4: "TR Target* TR'"
      by (auto simp add: STCal_steps)
    assume "TR'. TR Target* TR'  TQ'. TQ Target* TQ'  (TR', TQ')  (TRel+)¯"
    with B4 obtain TQ' where B5: "TQ Target* TQ'" and B6: "(TR', TQ')  (TRel+)¯"
      by blast
    from B6 have "(TQ', TR')  TRel+"
      by simp
    moreover from B2 B3 trel have "(TR', TP')  TRel+"
      by simp
    ultimately have "(TP', TQ')  (TRel+)¯"
      by simp
    with B5 show "TQ'. TQ Target* TQ'  (TP', TQ')  (TRel+)¯"
      by blast
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  shows "weak_reduction_simulation ((TRel+)¯) Target"
      using sim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_simulation_rev[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_reduction_simulation ((indRelLTPO TRel)¯) (STCal Source Target)"
  shows "weak_reduction_simulation ((TRel+)¯) Target"
      using sim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_simulation_rev[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "weak_reduction_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel*"
  shows "weak_reduction_simulation (TRel*) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel*" and "TP Target* TP'"
  thus "TQ'. TQ Target* TQ'  (TP', TQ')  TRel*"
  proof (induct arbitrary: TP')
    fix TP'
    assume "TP Target* TP'"
    moreover have "(TP', TP')  TRel*"
      by simp
    ultimately show "TQ'. TP Target* TQ'  (TP', TQ')  TRel*"
      by blast
  next
    case (step TQ TR)
    assume "TP Target* TP'"
       and "TP'. TP Target* TP'  TQ'. TQ Target* TQ'  (TP', TQ')  TRel*"
    from this obtain TQ' where B1: "TQ Target* TQ'" and B2: "(TP', TQ')  TRel*"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
      by (simp add: STCal_steps)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target)* R'"
                           and B4: "(TargetTerm TQ', R')  Rel"
        using sim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target* TR'"
      by (auto simp add: STCal_steps)
    from B4 B5 trel have "(TQ', TR')  TRel*"
      by simp
    with B2 have "(TP', TR')  TRel*"
      by simp
    with B6 show "TR'. TR Target* TR'  (TP', TR')  TRel*"
      by blast
  qed
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_reduction_simulation (indRelTEQ TRel) (STCal Source Target)"
  shows "weak_reduction_simulation (TRel*) Target"
      using sim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_simulation[where
             Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_transC_TRel_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "strong_reduction_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "strong_reduction_simulation (TRel+) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel+" and "TP Target TP'"
  thus "TQ'. TQ Target TQ'  (TP', TQ')  TRel+"
  proof (induct arbitrary: TP')
    fix TQ TP'
    assume "(TP, TQ)  TRel"
    with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP Target TP'"
    hence "TargetTerm TP (STCal Source Target) (TargetTerm TP')"
      by (simp add: STCal_step)
    ultimately obtain Q' where A2: "TargetTerm TQ (STCal Source Target) Q'"
                           and A3: "(TargetTerm TP', Q')  Rel"
        using sim
      by blast
    from A2 obtain TQ' where A4: "TQ Target TQ'" and A5: "TQ' ∈T Q'"
      by (auto simp add: STCal_step)
    from A3 A5 trel have "(TP', TQ')  TRel+"
      by simp
    with A4 show "TQ'. TQ Target TQ'  (TP', TQ')  TRel+"
      by blast
  next
    case (step TQ TR)
    assume "TP Target TP'"
       and "TP'. TP Target TP'  TQ'. TQ Target TQ'  (TP', TQ')  TRel+"
    from this obtain TQ' where B1: "TQ Target TQ'" and B2: "(TP', TQ')  TRel+"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target) (TargetTerm TQ')"
      by (simp add: STCal_step)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target) R'"
                           and B4: "(TargetTerm TQ', R')  Rel"
        using sim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target TR'"
      by (auto simp add: STCal_step)
    from B4 B5 trel have "(TQ', TR')  TRel+"
      by simp
    with B2 have "(TP', TR')  TRel+"
      by simp
    with B6 show "TR'. TR Target TR'  (TP', TR')  TRel+"
      by blast
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  shows "strong_reduction_simulation (TRel+) Target"
      using sim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_simulation[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_reduction_simulation (indRelLTPO TRel) (STCal Source Target)"
  shows "strong_reduction_simulation (TRel+) Target"
      using sim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_simulation[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_transC_TRel_is_strong_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "strong_reduction_simulation (Rel¯) (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "strong_reduction_simulation ((TRel+)¯) Target"
proof clarify
  fix TP TQ TP'
  assume "(TQ, TP)  TRel+"
  moreover assume "TP Target TP'"
  ultimately show "TQ'. TQ Target TQ'  (TP', TQ')  (TRel+)¯"
  proof (induct arbitrary: TP')
    fix TP TP'
    assume "(TQ, TP)  TRel"
    with target have "(TargetTerm TP, TargetTerm TQ)  Rel¯"
      by simp
    moreover assume "TP Target TP'"
    hence "TargetTerm TP (STCal Source Target) (TargetTerm TP')"
      by (simp add: STCal_step)
    ultimately obtain Q' where A2: "TargetTerm TQ (STCal Source Target) Q'"
                           and A3: "(TargetTerm TP', Q')  Rel¯"
        using sim
      by blast
    from A2 obtain TQ' where A4: "TQ Target TQ'" and A5: "TQ' ∈T Q'"
      by (auto simp add: STCal_step(2))
    from A3 A5 trel have "(TP', TQ')  (TRel+)¯"
      by simp
    with A4 show "TQ'. TQ Target TQ'  (TP', TQ')  (TRel+)¯"
      by blast
  next
    case (step TP TR TR')
    assume "(TP, TR)  TRel"
    with target have "(TargetTerm TP, TargetTerm TR)  Rel"
      by simp
    moreover assume "TR Target TR'"
    hence "TargetTerm TR (STCal Source Target) (TargetTerm TR')"
      by (simp add: STCal_step)
    ultimately obtain P' where B1: "TargetTerm TP (STCal Source Target) P'"
                           and B2: "(P', TargetTerm TR')  Rel"
        using sim
      by blast
    from B1 obtain TP' where B3: "TP' ∈T P'" and B4: "TP Target TP'"
      by (auto simp add: STCal_step)
    assume "TP'. TP Target TP'  TQ'. TQ Target TQ'  (TP', TQ')  (TRel+)¯"
    with B4 obtain TQ' where B5: "TQ Target TQ'" and B6: "(TP', TQ')  (TRel+)¯"
      by blast
    from B2 B3 trel have "(TP', TR')  TRel+"
      by simp
    with B6 have "(TR', TQ')  (TRel+)¯"
      by simp
    with B5 show "TQ'. TQ Target TQ'  (TR', TQ')  (TRel+)¯"
      by blast
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_strong_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  shows "strong_reduction_simulation ((TRel+)¯) Target"
      using sim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_simulation_rev[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_strong_reduction_simulation_rev:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_reduction_simulation ((indRelLTPO TRel)¯) (STCal Source Target)"
  shows "strong_reduction_simulation ((TRel+)¯) Target"
      using sim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_simulation_rev[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_reflC_transC_TRel_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes sim:    "strong_reduction_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel
                    (T1, T2)  TRel*"
  shows "strong_reduction_simulation (TRel*) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel*" and "TP Target TP'"
  thus "TQ'. TQ Target TQ'  (TP', TQ')  TRel*"
  proof (induct arbitrary: TP')
    fix TP'
    assume "TP Target TP'"
    moreover have "(TP', TP')  TRel*"
      by simp
    ultimately show "TQ'. TP Target TQ'  (TP', TQ')  TRel*"
      by blast
  next
    case (step TQ TR TP')
    assume "TP Target TP'"
       and "TP'. TP Target TP'  TQ'. TQ Target TQ'  (TP', TQ')  TRel*"
    from this obtain TQ' where B1: "TQ Target TQ'" and B2: "(TP', TQ')  TRel*"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target) (TargetTerm TQ')"
      by (simp add: STCal_step)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target) R'"
                           and B4: "(TargetTerm TQ', R')  Rel"
        using sim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target TR'"
      by (auto simp add: STCal_step)
    from B4 B5 trel have "(TQ', TR')  TRel*"
      by simp
    with B2 have "(TP', TR')  TRel*"
      by simp
    with B6 show "TR'. TR Target TR'  (TP', TR')  TRel*"
      by blast
  qed
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_reduction_simulation (indRelTEQ TRel) (STCal Source Target)"
  shows "strong_reduction_simulation (TRel*) Target"
      using sim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_strong_reduction_simulation[where
             Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_weak_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_barbed_simulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_simulation (TRel+) TWB"
proof
  from sim show "weak_reduction_simulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_weakly_preserves_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_weak_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_barbed_simulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_simulation (TRel+) TWB"
proof
  from sim show "weak_reduction_simulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_weakly_preserves_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_weak_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "weak_barbed_simulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_simulation (TRel*) TWB"
proof
  from sim show "weak_reduction_simulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_weakly_preserves_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_strong_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_barbed_simulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_simulation (TRel+) TWB"
proof
  from sim show "strong_reduction_simulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_strong_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_preserves_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_preserves_barbs[where TRel="TRel"]
            preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_strong_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_barbed_simulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_simulation (TRel+) TWB"
proof
  from sim refl show "strong_reduction_simulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_strong_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_preserves_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_preserves_barbs[where TRel="TRel"]
            preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_strong_barbed_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes sim: "strong_barbed_simulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_simulation (TRel*) TWB"
proof
  from sim refl show "strong_reduction_simulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_strong_reduction_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from sim show "rel_preserves_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_preserves_barbs[where TRel="TRel"]
            preservation_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

text ‹If indRelRTPO, indRelLTPO, or indRelTEQ is a contrasimulation then so is the corresponding
        target term relation.›

lemma (in encoding) rel_with_target_impl_transC_TRel_is_weak_reduction_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes conSim: "weak_reduction_contrasimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "weak_reduction_contrasimulation (TRel+) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel+" and "TP Target* TP'"
  thus "TQ'. TQ Target* TQ'  (TQ', TP')  TRel+"
  proof (induct arbitrary: TP')
    fix TQ TP'
    assume "(TP, TQ)  TRel"
    with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP Target* TP'"
    hence "TargetTerm TP (STCal Source Target)* (TargetTerm TP')"
      by (simp add: STCal_steps)
    ultimately obtain Q' where A2: "TargetTerm TQ (STCal Source Target)* Q'"
                           and A3: "(Q', TargetTerm TP')  Rel"
        using conSim
      by blast
    from A2 obtain TQ' where A4: "TQ Target* TQ'" and A5: "TQ' ∈T Q'"
      by (auto simp add: STCal_steps)
    from A3 A5 trel have "(TQ', TP')  TRel+"
      by simp
    with A4 show "TQ'. TQ Target* TQ'  (TQ', TP')  TRel+"
      by blast
  next
    case (step TQ TR)
    assume "TP Target* TP'"
       and "TP'. TP Target* TP'  TQ'. TQ Target* TQ'  (TQ', TP')  TRel+"
    from this obtain TQ' where B1: "TQ Target* TQ'" and B2: "(TQ', TP')  TRel+"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
      by (simp add: STCal_steps)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target)* R'"
                           and B4: "(R', TargetTerm TQ')  Rel"
        using conSim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target* TR'"
      by (auto simp add: STCal_steps)
    from B4 B5 trel have "(TR', TQ')  TRel+"
      by simp
    from this B2 have "(TR', TP')  TRel+"
      by simp
    with B6 show "TR'. TR Target* TR'  (TR', TP')  TRel+"
      by blast
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_reduction_contrasimulation (indRelRTPO TRel) (STCal Source Target)"
  shows "weak_reduction_contrasimulation (TRel+) Target"
      using conSim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_contrasimulation[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_reduction_contrasimulation (indRelLTPO TRel) (STCal Source Target)"
  shows "weak_reduction_contrasimulation (TRel+) Target"
      using conSim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_contrasimulation[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes conSim: "weak_reduction_contrasimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel*"
  shows "weak_reduction_contrasimulation (TRel*) Target"
proof clarify
  fix TP TQ TP'
  assume "(TP, TQ)  TRel*" and "TP Target* TP'"
  thus "TQ'. TQ Target* TQ'  (TQ', TP')  TRel*"
  proof (induct arbitrary: TP')
    fix TP'
    assume "TP Target* TP'"
    moreover have "(TP', TP')  TRel*"
      by simp
    ultimately show "TQ'. TP Target* TQ'  (TQ', TP')  TRel*"
      by blast
  next
    case (step TQ TR)
    assume "TP Target* TP'"
       and "TP'. TP Target* TP'  TQ'. TQ Target* TQ'  (TQ', TP')  TRel*"
    from this obtain TQ' where B1: "TQ Target* TQ'" and B2: "(TQ', TP')  TRel*"
      by blast
    assume "(TQ, TR)  TRel"
    with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
      by simp
    moreover from B1 have "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
      by (simp add: STCal_steps)
    ultimately obtain R' where B3: "TargetTerm TR (STCal Source Target)* R'"
                           and B4: "(R', TargetTerm TQ')  Rel"
        using conSim
      by blast
    from B3 obtain TR' where B5: "TR' ∈T R'" and B6: "TR Target* TR'"
      by (auto simp add: STCal_steps)
    from B4 B5 trel have "(TR', TQ')  TRel*"
      by simp
    from this B2 have "(TR', TP')  TRel*"
      by simp
    with B6 show "TR'. TR Target* TR'  (TR', TP')  TRel*"
      by blast
  qed
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_weak_reduction_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_reduction_contrasimulation (indRelTEQ TRel) (STCal Source Target)"
  shows "weak_reduction_contrasimulation (TRel*) Target"
      using conSim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_contrasimulation[where
             Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_weak_barbed_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_barbed_contrasimulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_contrasimulation (TRel+) TWB"
proof
  from conSim show "weak_reduction_contrasimulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from conSim show "rel_weakly_preserves_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_weak_barbed_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_barbed_contrasimulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_contrasimulation (TRel+) TWB"
proof
  from conSim show "weak_reduction_contrasimulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from conSim show "rel_weakly_preserves_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(2)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_weak_barbed_contrasimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes conSim: "weak_barbed_contrasimulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_contrasimulation (TRel*) TWB"
proof
  from conSim show "weak_reduction_contrasimulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from conSim show "rel_weakly_preserves_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_weakly_preserves_barbs[where TRel="TRel"]
            weak_preservation_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

text ‹If indRelRTPO, indRelLTPO, or indRelTEQ is a coupled simulation then so is the
        corresponding target term relation.›

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_reduction_coupled_simulation (indRelRTPO TRel) (STCal Source Target)"
  shows "weak_reduction_coupled_simulation (TRel+) Target"
      using couSim weak_reduction_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelRTPO_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
            indRelRTPO_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_reduction_coupled_simulation (indRelLTPO TRel) (STCal Source Target)"
  shows "weak_reduction_coupled_simulation (TRel+) Target"
      using couSim weak_reduction_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelLTPO_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
            indRelLTPO_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by blast

lemma (in encoding) indRelTEQ_impl_TRel_is_weak_reduction_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_reduction_coupled_simulation (indRelTEQ TRel) (STCal Source Target)"
  shows "weak_reduction_coupled_simulation (TRel*) Target"
      using couSim weak_reduction_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelTEQ_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
            indRelTEQ_impl_TRel_is_weak_reduction_contrasimulation[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_weak_barbed_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_barbed_coupled_simulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_coupled_simulation (TRel+) TWB"
      using couSim weak_barbed_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelRTPO_impl_TRel_is_weak_barbed_simulation[where TRel="TRel"]
            indRelRTPO_impl_TRel_is_weak_barbed_contrasimulation[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_weak_barbed_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_barbed_coupled_simulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_coupled_simulation (TRel+) TWB"
      using couSim weak_barbed_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelLTPO_impl_TRel_is_weak_barbed_simulation[where TRel="TRel"]
            indRelLTPO_impl_TRel_is_weak_barbed_contrasimulation[where TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_weak_barbed_coupled_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes couSim: "weak_barbed_coupled_simulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_coupled_simulation (TRel*) TWB"
      using couSim weak_barbed_coupled_simulation_versus_simulation_and_contrasimulation
            refl indRelTEQ_impl_TRel_is_weak_barbed_simulation[where TRel="TRel"]
            indRelTEQ_impl_TRel_is_weak_barbed_contrasimulation[where TRel="TRel"]
    by blast

text ‹If indRelRTPO, indRelLTPO, or indRelTEQ is a correspondence simulation then so is the
        corresponding target term relation.›

lemma (in encoding) rel_with_target_impl_transC_TRel_is_weak_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes corSim: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "weak_reduction_correspondence_simulation (TRel+) Target"
proof -
  from corSim target trel have A: "weak_reduction_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_weak_reduction_simulation[where TRel="TRel"
             and Rel="Rel"]
    by blast
  moreover have "P Q Q'. (P, Q)  TRel+  Q Target* Q'
                  (P'' Q''. P Target* P''  Q' Target* Q''  (P'', Q'')  TRel+)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel+" and "TQ Target* TQ'"
    thus "TP'' TQ''. TP Target* TP''  TQ' Target* TQ''  (TP'', TQ'')  TRel+"
    proof (induct arbitrary: TQ')
      fix TQ TQ'
      assume "(TP, TQ)  TRel"
      with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
        by blast
      moreover assume "TQ Target* TQ'"
      hence "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
        by (simp add: STCal_steps)
      ultimately obtain P'' Q'' where A2: "TargetTerm TP (STCal Source Target)* P''"
        and A3: "TargetTerm TQ' (STCal Source Target)* Q''" and A4: "(P'', Q'')  Rel"
          using corSim
        by blast
      from A2 obtain TP'' where A5: "TP Target* TP''" and A6: "TP'' ∈T P''"
        by (auto simp add: STCal_steps)
      from A3 obtain TQ'' where A7: "TQ' Target* TQ''" and A8: "TQ'' ∈T Q''"
        by (auto simp add: STCal_steps)
      from A4 A6 A8 trel have "(TP'', TQ'')  TRel+"
        by blast
      with A5 A7
      show "TP'' TQ''. TP Target* TP''  TQ' Target* TQ''  (TP'', TQ'')  TRel+"
        by blast
    next
      case (step TQ TR TR')
      assume "TQ'. TQ Target* TQ' TP'' TQ''. TP Target* TP''  TQ' Target* TQ''
               (TP'', TQ'')  TRel+"
      moreover assume "(TQ, TR)  TRel"
      hence "TR'. TR Target* TR'
              (TQ'' TR''. TQ Target* TQ''  TR' Target* TR''  (TQ'', TR'')  TRel+)"
      proof clarify
        fix TR'
        assume "(TQ, TR)  TRel"
        with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
          by simp
        moreover assume "TR Target* TR'"
        hence "TargetTerm TR (STCal Source Target)* (TargetTerm TR')"
          by (simp add: STCal_steps)
        ultimately obtain Q'' R'' where B1: "TargetTerm TQ (STCal Source Target)* Q''"
         and B2: "TargetTerm TR' (STCal Source Target)* R''" and B3: "(Q'', R'')  Rel"
            using corSim
          by blast
        from B1 obtain TQ'' where B4: "TQ'' ∈T Q''" and B5: "TQ Target* TQ''"
          by (auto simp add: STCal_steps)
        from B2 obtain TR'' where B6: "TR'' ∈T R''" and B7: "TR' Target* TR''"
          by (auto simp add: STCal_steps)
        from B3 B4 B6 trel have "(TQ'', TR'')  TRel+"
          by simp
        with B5 B7
        show "TQ'' TR''. TQ Target* TQ''  TR' Target* TR''  (TQ'', TR'')  TRel+"
          by blast
      qed
      moreover have "trans (TRel+)"
        by simp
      moreover assume "TR Target* TR'"
      ultimately
      show "TP'' TR''. TP Target* TP''  TR' Target* TR''  (TP'', TR'')  TRel+"
        using A reduction_correspondence_simulation_condition_trans[where Rel="TRel+"
                and Cal="Target"]
        by blast
    qed
  qed
  ultimately show ?thesis
    by simp
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes cSim: "weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
  shows "weak_reduction_correspondence_simulation (TRel+) Target"
      using cSim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_correspondence_simulation[where
              Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes cSim: "weak_reduction_correspondence_simulation (indRelLTPO TRel) (STCal Source Target)"
  shows "weak_reduction_correspondence_simulation (TRel+) Target"
      using cSim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_correspondence_simulation[where
              Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding)
  rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes corSim: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel*"
  shows "weak_reduction_correspondence_simulation (TRel*) Target"
proof -
  from corSim target trel have A: "weak_reduction_simulation (TRel*) Target"
      using rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_simulation[where TRel="TRel"
             and Rel="Rel"]
    by blast
  moreover have "P Q Q'. (P, Q)  TRel*  Q Target* Q' 
    (P'' Q''. P Target* P''  Q' Target* Q''  (P'', Q'')  TRel*)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel*" and "TQ Target* TQ'"
    thus "TP'' TQ''. TP Target* TP''  TQ' Target* TQ''  (TP'', TQ'')  TRel*"
    proof (induct arbitrary: TQ')
      fix TQ'
      assume "TP Target* TQ'"
      moreover have "TQ' Target* TQ'"
        by (simp add: steps_refl)
      moreover have "(TQ', TQ')  TRel*"
        by simp
      ultimately show "TP'' TQ''. TP Target* TP''  TQ' Target* TQ''  (TP'', TQ'')  TRel*"
        by blast
    next
      case (step TQ TR TR')
      assume "TQ'. TQ Target* TQ' TP'' TQ''. TP Target* TP''  TQ' Target* TQ''
               (TP'', TQ'')  TRel*"
      moreover assume "(TQ, TR)  TRel"
      with corSim have "TR'. TR Target* TR'  TQ'' TR''. TQ Target* TQ''
                         TR' Target* TR''  (TQ'', TR'')  TRel*"
      proof clarify
        fix TR'
        assume "(TQ, TR)  TRel"
        with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
          by simp
        moreover assume "TR Target* TR'"
        hence "TargetTerm TR (STCal Source Target)* (TargetTerm TR')"
          by (simp add: STCal_steps)
        ultimately obtain Q'' R'' where B1: "TargetTerm TQ (STCal Source Target)* Q''"
         and B2: "TargetTerm TR' (STCal Source Target)* R''" and B3: "(Q'', R'')  Rel"
            using corSim
          by blast
        from B1 obtain TQ'' where B4: "TQ'' ∈T Q''" and B5: "TQ Target* TQ''"
          by (auto simp add: STCal_steps)
        from B2 obtain TR'' where B6: "TR'' ∈T R''" and B7: "TR' Target* TR''"
          by (auto simp add: STCal_steps)
        from B3 B4 B6 trel have "(TQ'', TR'')  TRel*"
          by simp
        with B5 B7
        show "TQ'' TR''. TQ Target* TQ''  TR' Target* TR''  (TQ'', TR'')  TRel*"
          by blast
      qed
      moreover assume "TR Target* TR'"
      moreover have "trans (TRel*)"
          using trans_rtrancl[of TRel]
        by simp
      ultimately show "TP'' TR''. TP Target* TP''  TR' Target* TR''  (TP'', TR'')  TRel*"
        using A reduction_correspondence_simulation_condition_trans[where Rel="TRel*"
                and Cal="Target"]
        by blast
    qed
  qed
  ultimately show ?thesis
    by simp
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_weak_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes corSim: "weak_reduction_correspondence_simulation (indRelTEQ TRel) (STCal Source Target)"
  shows "weak_reduction_correspondence_simulation (TRel*) Target"
      using corSim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_correspondence_simulation[
              where Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_weak_barbed_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes corSim: "weak_barbed_correspondence_simulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_correspondence_simulation (TRel+) TWB"
proof
  from corSim show "weak_reduction_correspondence_simulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_weak_reduction_correspondence_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from corSim show "rel_weakly_respects_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_weak_barbed_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes corSim: "weak_barbed_correspondence_simulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_correspondence_simulation (TRel+) TWB"
proof
  from corSim show "weak_reduction_correspondence_simulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_weak_reduction_correspondence_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from corSim show "rel_weakly_respects_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_weak_barbed_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes corSim: "weak_barbed_correspondence_simulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_correspondence_simulation (TRel*) TWB"
proof
  from corSim show "weak_reduction_correspondence_simulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_weak_reduction_correspondence_simulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from corSim show "rel_weakly_respects_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(5)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

text ‹If indRelRTPO, indRelLTPO, or indRelTEQ is a bisimulation then so is the corresponding
        target term relation.›

lemma (in encoding) rel_with_target_impl_transC_TRel_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes bisim:  "weak_reduction_bisimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "weak_reduction_bisimulation (TRel+) Target"
proof
  from bisim target trel show "weak_reduction_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_weak_reduction_simulation[where TRel="TRel"
             and Rel="Rel"]
    by blast
next
  show "P Q Q'. (P, Q)  TRel+  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel+)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel+" and "TQ Target* TQ'"
    thus "TP'. TP Target* TP'  (TP', TQ')  TRel+"
    proof (induct arbitrary: TQ')
      fix TQ TQ'
      assume "(TP, TQ)  TRel"
      with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
        by simp
      moreover assume "TQ Target* TQ'"
      hence "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
        by (simp add: STCal_steps)
      ultimately obtain P' where A2: "TargetTerm TP (STCal Source Target)* P'"
                             and A3: "(P', TargetTerm TQ')  Rel"
          using bisim
        by blast
      from A2 obtain TP' where A4: "TP Target* TP'" and A5: "TP' ∈T P'"
        by (auto simp add: STCal_steps)
      from A3 A5 trel have "(TP', TQ')  TRel+"
        by simp
      with A4 show "TP'. TP Target* TP'  (TP', TQ')  TRel+"
        by blast
    next
      case (step TQ TR TR')
      assume "(TQ, TR)  TRel"
      with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
        by simp
      moreover assume "TR Target* TR'"
      hence "TargetTerm TR (STCal Source Target)* (TargetTerm TR')"
        by (simp add: STCal_steps)
      ultimately obtain Q' where B1: "TargetTerm TQ (STCal Source Target)* Q'"
                             and B2: "(Q', TargetTerm TR')  Rel"
          using bisim
        by blast
      from B1 obtain TQ' where B3: "TQ' ∈T Q'" and B4: "TQ Target* TQ'"
        by (auto simp add: STCal_steps)
      assume "TQ'. TQ Target* TQ'  TP'. TP Target* TP'  (TP', TQ')  TRel+"
      with B4 obtain TP' where B5: "TP Target* TP'" and B6: "(TP', TQ')  TRel+"
        by blast
      from B2 B3 trel have "(TQ', TR')  TRel+"
        by simp
      with B6 have "(TP', TR')  TRel+"
        by simp
      with B5 show "TP'. TP Target* TP'  (TP', TR')  TRel+"
        by blast
    qed
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
  shows "weak_reduction_bisimulation (TRel+) Target"
      using bisim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_bisimulation[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_reduction_bisimulation (indRelLTPO TRel) (STCal Source Target)"
  shows "weak_reduction_bisimulation (TRel+) Target"
      using bisim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_bisimulation[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes bisim:  "weak_reduction_bisimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel*"
  shows "weak_reduction_bisimulation (TRel*) Target"
proof
  from bisim target trel show "weak_reduction_simulation (TRel*) Target"
      using rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_simulation[where TRel="TRel"
             and Rel="Rel"]
    by blast
next
  show "P Q Q'. (P, Q)  TRel*  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel*)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel*" and "TQ Target* TQ'"
    thus "TP'. TP Target* TP'  (TP', TQ')  TRel*"
    proof (induct arbitrary: TQ')
      fix TQ'
      assume "TP Target* TQ'"
      moreover have "(TQ', TQ')  TRel*"
        by simp
      ultimately show "TP'. TP Target* TP'  (TP', TQ')  TRel*"
        by blast
    next
      case (step TQ TR TR')
      assume "(TQ, TR)  TRel"
      with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
        by simp
      moreover assume "TR Target* TR'"
      hence "TargetTerm TR (STCal Source Target)* (TargetTerm TR')"
        by (simp add: STCal_steps)
      ultimately obtain Q' where B1: "TargetTerm TQ (STCal Source Target)* Q'"
                             and B2: "(Q', TargetTerm TR')  Rel"
          using bisim
        by blast
      from B1 obtain TQ' where B3: "TQ' ∈T Q'" and B4: "TQ Target* TQ'"
        by (auto simp add: STCal_steps)
      assume "TQ'. TQ Target* TQ'  TP'. TP Target* TP'  (TP', TQ')  TRel*"
      with B4 obtain TP' where B5: "TP Target* TP'" and B6: "(TP', TQ')  TRel*"
        by blast
      from B2 B3 trel have "(TQ', TR')  TRel*"
        by simp
      with B6 have "(TP', TR')  TRel*"
        by simp
      with B5 show "TP'. TP Target* TP'  (TP', TR')  TRel*"
        by blast
    qed
  qed
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  shows "weak_reduction_bisimulation (TRel*) Target"
      using bisim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_weak_reduction_bisimulation[where
             Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_transC_TRel_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes bisim:  "strong_reduction_bisimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  shows "strong_reduction_bisimulation (TRel+) Target"
proof
  from bisim target trel show "strong_reduction_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_strong_reduction_simulation[where Rel="Rel"
              and TRel="TRel"]
    by blast
next
  show "P Q Q'. (P, Q)  TRel+  Q Target Q'  (P'. P Target P'  (P', Q')  TRel+)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel+" and "TQ Target TQ'"
    thus "TP'. TP Target TP'  (TP', TQ')  TRel+"
    proof (induct arbitrary: TQ')
      fix TQ TQ'
      assume "(TP, TQ)  TRel"
      with target have "(TargetTerm TP, TargetTerm TQ)  Rel"
        by simp
      moreover assume "TQ Target TQ'"
      hence "TargetTerm TQ (STCal Source Target) (TargetTerm TQ')"
        by (simp add: STCal_step)
      ultimately obtain P' where A2: "TargetTerm TP (STCal Source Target) P'"
                             and A3: "(P', TargetTerm TQ')  Rel"
          using bisim
        by blast
      from A2 obtain TP' where A4: "TP Target TP'" and A5: "TP' ∈T P'"
        by (auto simp add: STCal_step)
      from A3 A5 trel have "(TP', TQ')  TRel+"
        by simp
      with A4 show "TP'. TP Target TP'  (TP', TQ')  TRel+"
        by blast
    next
      case (step TQ TR TR')
      assume "(TQ, TR)  TRel"
      with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
        by simp
      moreover assume "TR Target TR'"
      hence "TargetTerm TR (STCal Source Target) (TargetTerm TR')"
        by (simp add: STCal_step)
      ultimately obtain Q' where B1: "TargetTerm TQ (STCal Source Target) Q'"
                             and B2: "(Q', TargetTerm TR')  Rel"
          using bisim
        by blast
      from B1 obtain TQ' where B3: "TQ' ∈T Q'" and B4: "TQ Target TQ'"
        by (auto simp add: STCal_step)
      assume "TQ'. TQ Target TQ'  TP'. TP Target TP'  (TP', TQ')  TRel+"
      with B4 obtain TP' where B5: "TP Target TP'" and B6: "(TP', TQ')  TRel+"
        by blast
      from B2 B3 trel have "(TQ', TR')  TRel+"
        by simp
      with B6 have "(TP', TR')  TRel+"
        by simp
      with B5 show "TP'. TP Target TP'  (TP', TR')  TRel+"
        by blast
    qed
  qed
qed

lemma (in encoding) indRelRTPO_impl_TRel_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
  shows "strong_reduction_bisimulation (TRel+) Target"
      using bisim indRelRTPO.target[where TRel="TRel"] indRelRTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_bisimulation[where
             Rel="indRelRTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) indRelLTPO_impl_TRel_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_reduction_bisimulation (indRelLTPO TRel) (STCal Source Target)"
  shows "strong_reduction_bisimulation (TRel+) Target"
      using bisim indRelLTPO.target[where TRel="TRel"] indRelLTPO_to_TRel(4)[where TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_strong_reduction_bisimulation[where
             Rel="indRelLTPO TRel" and TRel="TRel"]
    by blast

lemma (in encoding) rel_with_target_impl_reflC_transC_TRel_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes bisim:  "strong_reduction_bisimulation Rel (STCal Source Target)"
      and target: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      and trel:   "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel*"
  shows "strong_reduction_bisimulation (TRel*) Target"
proof
  from bisim target trel show "strong_reduction_simulation (TRel*) Target"
      using rel_with_target_impl_reflC_transC_TRel_is_strong_reduction_simulation[where Rel="Rel"
              and TRel="TRel"]
    by blast
next
  show "P Q Q'. (P, Q)  TRel*  Q Target Q'  (P'. P Target P'  (P', Q')  TRel*)"
  proof clarify
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel*" and "TQ Target TQ'"
    thus "TP'. TP Target TP'  (TP', TQ')  TRel*"
    proof (induct arbitrary: TQ')
      fix TQ'
      assume "TP Target TQ'"
      thus "TP'. TP Target TP'  (TP', TQ')  TRel*"
        by blast
    next
      case (step TQ TR TR')
      assume "(TQ, TR)  TRel"
      with target have "(TargetTerm TQ, TargetTerm TR)  Rel"
        by simp
      moreover assume "TR Target TR'"
      hence "TargetTerm TR (STCal Source Target) (TargetTerm TR')"
        by (simp add: STCal_step)
      ultimately obtain Q' where B1: "TargetTerm TQ (STCal Source Target) Q'"
                             and B2: "(Q', TargetTerm TR')  Rel"
          using bisim
        by blast
      from B1 obtain TQ' where B3: "TQ' ∈T Q'" and B4: "TQ Target TQ'"
        by (auto simp add: STCal_step)
      assume "TQ'. TQ Target TQ'  TP'. TP Target TP'  (TP', TQ')  TRel*"
      with B4 obtain TP' where B5: "TP Target TP'" and B6: "(TP', TQ')  TRel*"
        by blast
      from B2 B3 trel have "(TQ', TR')  TRel*"
        by simp
      with B6 have "(TP', TR')  TRel*"
        by simp
      with B5 show "TP'. TP Target TP'  (TP', TR')  TRel*"
        by blast
    qed
  qed
qed

lemma (in encoding) indRelTEQ_impl_TRel_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  shows "strong_reduction_bisimulation (TRel*) Target"
      using bisim indRelTEQ.target[where TRel="TRel"] indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond
            rel_with_target_impl_reflC_transC_TRel_is_strong_reduction_bisimulation[where
             Rel="indRelTEQ TRel" and TRel="TRel"]
    by blast

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_weak_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_barbed_bisimulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_bisimulation (TRel+) TWB"
proof
  from bisim show "weak_reduction_bisimulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_weak_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_weakly_respects_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_weak_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_barbed_bisimulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_bisimulation (TRel+) TWB"
proof
  from bisim show "weak_reduction_bisimulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_weak_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_weakly_respects_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_weak_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "weak_barbed_bisimulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "weak_barbed_bisimulation (TRel*) TWB"
proof
  from bisim show "weak_reduction_bisimulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_weak_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_weakly_respects_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_weakly_respects_barbs[where TRel="TRel"]
            weak_respection_of_barbs_and_closures(5)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelRTPO_impl_TRel_is_strong_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_barbed_bisimulation (indRelRTPO TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_bisimulation (TRel+) TWB"
proof
  from bisim show "strong_reduction_bisimulation (TRel+) (Calculus TWB)"
      using indRelRTPO_impl_TRel_is_strong_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_respects_barbs (TRel+) TWB"
      using indRelRTPO_impl_TRel_respects_barbs[where TRel="TRel"]
            respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLTPO_impl_TRel_is_strong_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_barbed_bisimulation (indRelLTPO TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_bisimulation (TRel+) TWB"
proof
  from bisim refl show "strong_reduction_bisimulation (TRel+) (Calculus TWB)"
      using indRelLTPO_impl_TRel_is_strong_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_respects_barbs (TRel+) TWB"
      using indRelLTPO_impl_TRel_respects_barbs[where TRel="TRel"]
            respection_of_barbs_and_closures(3)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelTEQ_impl_TRel_is_strong_barbed_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes bisim: "strong_barbed_bisimulation (indRelTEQ TRel) (STCalWB SWB TWB)"
  shows "strong_barbed_bisimulation (TRel*) TWB"
proof
  from bisim refl show "strong_reduction_bisimulation (TRel*) (Calculus TWB)"
      using indRelTEQ_impl_TRel_is_strong_reduction_bisimulation[where TRel="TRel"]
    by (simp add: STCalWB_def calS calT)
next
  from bisim show "rel_respects_barbs (TRel*) TWB"
      using indRelTEQ_impl_TRel_respects_barbs[where TRel="TRel"]
            respection_of_barbs_and_closures(5)[where Rel="TRel" and CWB="TWB"]
    by blast
qed

subsection ‹Relations Induced by the Encoding and Relations on Source Terms and Target Terms›

text ‹Some encodability like e.g. full abstraction are defined w.r.t. a relation on source terms
        and a relation on target terms. To analyse such criteria we include these two relations in
        the considered relation on the disjoint union of source and target terms.›

inductive_set (in encoding) indRelRST
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelRST SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelRST SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelRST SRel TRel"

abbreviation (in encoding) indRelRSTinfix
    :: "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
         ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧R<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧R<SRel,TRel> Q  (P, Q)  indRelRST SRel TRel"

inductive_set (in encoding) indRelRSTPO
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelRSTPO SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelRSTPO SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelRSTPO SRel TRel" |
  trans:  "(P, Q)  indRelRSTPO SRel TRel; (Q, R)  indRelRSTPO SRel TRel
            (P, R)  indRelRSTPO SRel TRel"

abbreviation (in encoding) indRelRSTPOinfix ::
    "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
      ('procS, 'procT) Proc  bool" ("_ ≲⟦⋅⟧R<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ≲⟦⋅⟧R<SRel,TRel> Q  (P, Q)  indRelRSTPO SRel TRel"

lemma (in encoding) indRelRSTPO_refl:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflS: "refl SRel"
      and reflT: "refl TRel"
  shows "refl (indRelRSTPO SRel TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧R<SRel,TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    with reflS show "P ≲⟦⋅⟧R<SRel,TRel> P"
        unfolding refl_on_def
      by (simp add: indRelRSTPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with reflT show "P ≲⟦⋅⟧R<SRel,TRel> P"
        unfolding refl_on_def
      by (simp add: indRelRSTPO.target)
  qed
qed

lemma (in encoding) indRelRSTPO_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "trans (indRelRSTPO SRel TRel)"
    unfolding trans_def
proof clarify
  fix P Q R
  assume "P ≲⟦⋅⟧R<SRel,TRel> Q" and "Q ≲⟦⋅⟧R<SRel,TRel> R"
  thus "P ≲⟦⋅⟧R<SRel,TRel> R"
    by (rule indRelRSTPO.trans)
qed

lemma (in encoding) refl_trans_closure_of_indRelRST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflS: "refl SRel"
      and reflT: "refl TRel"
  shows "indRelRSTPO SRel TRel = (indRelRST SRel TRel)*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧R<SRel,TRel> Q"
  thus "(P, Q)  (indRelRST SRel TRel)*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (indRelRST SRel TRel)*"
        using indRelRST.encR[of S SRel TRel]
      by simp
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  (indRelRST SRel TRel)*"
        using indRelRST.source[of S1 S2 SRel TRel]
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelRST SRel TRel)*"
        using indRelRST.target[of T1 T2 TRel SRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelRST SRel TRel)*" and "(Q, R)  (indRelRST SRel TRel)*"
    thus "(P, R)  (indRelRST SRel TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelRST SRel TRel)*"
  thus "P ≲⟦⋅⟧R<SRel,TRel> Q"
  proof induct
    from reflS reflT show "P ≲⟦⋅⟧R<SRel,TRel> P"
        using indRelRSTPO_refl[of SRel TRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧R<SRel,TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧R<SRel,TRel> R"
    hence "Q ≲⟦⋅⟧R<SRel,TRel> R"
      by (induct, simp_all add: indRelRSTPO.intros)
    ultimately show "P ≲⟦⋅⟧R<SRel,TRel> R"
      by (rule indRelRSTPO.trans)
  qed
qed

inductive_set (in encoding) indRelLST
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encL:   "(TargetTerm (S), SourceTerm S)  indRelLST SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelLST SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelLST SRel TRel"

abbreviation (in encoding) indRelLSTinfix
    :: "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
         ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧L<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧L<SRel,TRel> Q  (P, Q)  indRelLST SRel TRel"

inductive_set (in encoding) indRelLSTPO
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encL:   "(TargetTerm (S), SourceTerm S)  indRelLSTPO SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelLSTPO SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelLSTPO SRel TRel" |
  trans:  "(P, Q)  indRelLSTPO SRel TRel; (Q, R)  indRelLSTPO SRel TRel
            (P, R)  indRelLSTPO SRel TRel"

abbreviation (in encoding) indRelLSTPOinfix
    :: "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
         ('procS, 'procT) Proc  bool" ("_ ≲⟦⋅⟧L<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ≲⟦⋅⟧L<SRel,TRel> Q  (P, Q)  indRelLSTPO SRel TRel"

lemma (in encoding) indRelLSTPO_refl:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflS: "refl SRel"
      and reflT: "refl TRel"
  shows "refl (indRelLSTPO SRel TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ≲⟦⋅⟧L<SRel,TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    with reflS show "P ≲⟦⋅⟧L<SRel,TRel> P"
        unfolding refl_on_def
      by (simp add: indRelLSTPO.source)
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with reflT show "P ≲⟦⋅⟧L<SRel,TRel> P"
        unfolding refl_on_def
      by (simp add: indRelLSTPO.target)
  qed
qed

lemma (in encoding) indRelLSTPO_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "trans (indRelLSTPO SRel TRel)"
    unfolding trans_def
proof clarify
  fix P Q R
  assume "P ≲⟦⋅⟧L<SRel,TRel> Q" and "Q ≲⟦⋅⟧L<SRel,TRel> R"
  thus "P ≲⟦⋅⟧L<SRel,TRel> R"
    by (rule indRelLSTPO.trans)
qed

lemma (in encoding) refl_trans_closure_of_indRelLST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflS: "refl SRel"
      and reflT: "refl TRel"
  shows "indRelLSTPO SRel TRel = (indRelLST SRel TRel)*"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧L<SRel,TRel> Q"
  thus "(P, Q)  (indRelLST SRel TRel)*"
  proof induct
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (indRelLST SRel TRel)*"
        using indRelLST.encL[of S SRel TRel]
      by simp
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  (indRelLST SRel TRel)*"
        using indRelLST.source[of S1 S2 SRel TRel]
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelLST SRel TRel)*"
        using indRelLST.target[of T1 T2 TRel SRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelLST SRel TRel)*" and "(Q, R)  (indRelLST SRel TRel)*"
    thus "(P, R)  (indRelLST SRel TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelLST SRel TRel)*"
  thus "P ≲⟦⋅⟧L<SRel,TRel> Q"
  proof induct
    from reflS reflT show " P ≲⟦⋅⟧L<SRel,TRel> P"
        using indRelLSTPO_refl[of SRel TRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ≲⟦⋅⟧L<SRel,TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧L<SRel,TRel> R"
    hence "Q ≲⟦⋅⟧L<SRel,TRel> R"
      by (induct, simp_all add: indRelLSTPO.intros)
    ultimately show "P ≲⟦⋅⟧L<SRel,TRel> R"
      by (rule indRelLSTPO.trans)
  qed
qed

inductive_set (in encoding) indRelST
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelST SRel TRel" |
  encL:   "(TargetTerm (S), SourceTerm S)  indRelST SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelST SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelST SRel TRel"

abbreviation (in encoding) indRelSTinfix
    :: "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
         ('procS, 'procT) Proc  bool" ("_ ℛ⟦⋅⟧<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ℛ⟦⋅⟧<SRel,TRel> Q  (P, Q)  indRelST SRel TRel"

lemma (in encoding) indRelST_symm:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "sym (indRelST SRel TRel)"
    unfolding sym_def
proof clarify
  fix P Q
  assume "(P, Q)  indRelST SRel TRel"
  thus "(Q, P)  indRelST SRel TRel"
  proof induct
    case (encR S)
    show "(TargetTerm (S), SourceTerm S)  indRelST SRel TRel"
      by (rule indRelST.encL)
  next
    case (encL S)
    show "(SourceTerm S, TargetTerm (S))  indRelST SRel TRel"
      by (rule indRelST.encR)
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    with symmS show "(SourceTerm S2, SourceTerm S1)  indRelST SRel TRel"
        unfolding sym_def
      by (simp add: indRelST.source)
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    with symmT show "(TargetTerm T2, TargetTerm T1)  indRelST SRel TRel"
        unfolding sym_def
      by (simp add: indRelST.target)
  qed
qed

inductive_set (in encoding) indRelSTEQ
    :: "('procS × 'procS) set  ('procT × 'procT) set
         ((('procS, 'procT) Proc) × (('procS, 'procT) Proc)) set"
    for SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  where
  encR:   "(SourceTerm S, TargetTerm (S))  indRelSTEQ SRel TRel" |
  encL:   "(TargetTerm (S), SourceTerm S)  indRelSTEQ SRel TRel" |
  source: "(S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  indRelSTEQ SRel TRel" |
  target: "(T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  indRelSTEQ SRel TRel" |
  trans:  "(P, Q)  indRelSTEQ SRel TRel; (Q, R)  indRelSTEQ SRel TRel
            (P, R)  indRelSTEQ SRel TRel"

abbreviation (in encoding) indRelSTEQinfix
    :: "('procS, 'procT) Proc  ('procS × 'procS) set  ('procT × 'procT) set
         ('procS, 'procT) Proc  bool" ("_ ∼⟦⋅⟧<_,_> _" [75, 75, 75, 75] 80)
  where
  "P ∼⟦⋅⟧<SRel,TRel> Q  (P, Q)  indRelSTEQ SRel TRel"

lemma (in encoding) indRelSTEQ_refl:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
  shows "refl (indRelSTEQ SRel TRel)"
    unfolding refl_on_def
proof auto
  fix P
  show "P ∼⟦⋅⟧<SRel,TRel> P"
  proof (cases P)
    case (SourceTerm SP)
    assume "SP ∈S P"
    moreover have "SourceTerm SP ∼⟦⋅⟧<SRel,TRel> TargetTerm (SP)"
      by (rule indRelSTEQ.encR)
    moreover have "TargetTerm (SP) ∼⟦⋅⟧<SRel,TRel> SourceTerm SP"
      by (rule indRelSTEQ.encL)
    ultimately show "P ∼⟦⋅⟧<SRel,TRel> P"
      by (simp add: indRelSTEQ.trans[where P="SourceTerm SP" and Q="TargetTerm (SP)"])
  next
    case (TargetTerm TP)
    assume "TP ∈T P"
    with reflT show "P ∼⟦⋅⟧<SRel,TRel> P"
        unfolding refl_on_def
      by (simp add: indRelSTEQ.target)
  qed
qed

lemma (in encoding) indRelSTEQ_symm:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "sym (indRelSTEQ SRel TRel)"
    unfolding sym_def
proof clarify
  fix P Q
  assume "P ∼⟦⋅⟧<SRel,TRel> Q"
  thus "Q ∼⟦⋅⟧<SRel,TRel> P"
  proof induct
    case (encR S)
    show "TargetTerm (S) ∼⟦⋅⟧<SRel,TRel> SourceTerm S"
      by (rule indRelSTEQ.encL)
  next
    case (encL S)
    show "SourceTerm S ∼⟦⋅⟧<SRel,TRel> TargetTerm (S)"
      by (rule indRelSTEQ.encR)
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    with symmS show "SourceTerm S2 ∼⟦⋅⟧<SRel,TRel> SourceTerm S1"
        unfolding sym_def
      by (simp add: indRelSTEQ.source)
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    with symmT show "TargetTerm T2 ∼⟦⋅⟧<SRel,TRel> TargetTerm T1"
        unfolding sym_def
      by (simp add: indRelSTEQ.target)
  next
    case (trans P Q R)
    assume "R ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> P"
    thus "R ∼⟦⋅⟧<SRel,TRel> P"
      by (rule indRelSTEQ.trans)
  qed
qed

lemma (in encoding) indRelSTEQ_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "trans (indRelSTEQ SRel TRel)"
    unfolding trans_def
proof clarify
  fix P Q R
  assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
  thus "P ∼⟦⋅⟧<SRel,TRel> R"
    by (rule indRelSTEQ.trans)
qed

lemma (in encoding) refl_trans_closure_of_indRelST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
  shows "indRelSTEQ SRel TRel = (indRelST SRel TRel)*"
proof auto
  fix P Q
  assume "P ∼⟦⋅⟧<SRel,TRel> Q"
  thus "(P, Q)  (indRelST SRel TRel)*"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (indRelST SRel TRel)*"
        using indRelST.encR[of S SRel TRel]
      by simp
  next
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (indRelST SRel TRel)*"
        using indRelST.encL[of S SRel TRel]
      by simp
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  (indRelST SRel TRel)*"
        using indRelST.source[of S1 S2 SRel TRel]
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (indRelST SRel TRel)*"
        using indRelST.target[of T1 T2 TRel SRel]
      by simp
  next
    case (trans P Q R)
    assume "(P, Q)  (indRelST SRel TRel)*" and "(Q, R)  (indRelST SRel TRel)*"
    thus "(P, R)  (indRelST SRel TRel)*"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (indRelST SRel TRel)*"
  thus "P ∼⟦⋅⟧<SRel,TRel> Q"
  proof induct
    from reflT show "P ∼⟦⋅⟧<SRel,TRel> P"
        using indRelSTEQ_refl[of TRel SRel]
        unfolding refl_on_def
      by simp
  next
    case (step Q R)
    assume "P ∼⟦⋅⟧<SRel,TRel> Q"
    moreover assume "Q ℛ⟦⋅⟧<SRel,TRel> R"
    hence "Q ∼⟦⋅⟧<SRel,TRel> R"
      by (induct, simp_all add: indRelSTEQ.intros)
    ultimately show "P ∼⟦⋅⟧<SRel,TRel> R"
      by (rule indRelSTEQ.trans)
  qed
qed

lemma (in encoding) refl_symm_trans_closure_of_indRelST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
      and symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "indRelSTEQ SRel TRel = (symcl ((indRelST SRel TRel)=))+"
proof -
  have "(symcl ((indRelST SRel TRel)=))+ = (symcl (indRelST SRel TRel))*"
    by (rule refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelST SRel TRel"])
  moreover from symmS symmT have "symcl (indRelST SRel TRel) = indRelST SRel TRel"
      using indRelST_symm[where SRel="SRel" and TRel="TRel"]
            symm_closure_of_symm_rel[where Rel="indRelST SRel TRel"]
    by blast
  ultimately show "indRelSTEQ SRel TRel = (symcl ((indRelST SRel TRel)=))+"
      using reflT refl_trans_closure_of_indRelST[where SRel="SRel" and TRel="TRel"]
    by simp
qed

lemma (in encoding) symm_closure_of_indRelRST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
      and symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "indRelST SRel TRel = symcl (indRelRST SRel TRel)"
    and "indRelSTEQ SRel TRel = (symcl ((indRelRST SRel TRel)=))+"
proof -
  show "indRelST SRel TRel = symcl (indRelRST SRel TRel)"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧<SRel,TRel> Q"
    thus "(P, Q)  symcl (indRelRST SRel TRel)"
      by (induct, simp_all add: symcl_def indRelRST.intros)
  next
    fix P Q
    assume "(P, Q)  symcl (indRelRST SRel TRel)"
    thus "P ℛ⟦⋅⟧<SRel,TRel> Q"
    proof (auto simp add: symcl_def indRelRST.simps)
      fix S
      show "SourceTerm S ℛ⟦⋅⟧<SRel,TRel> TargetTerm (S)"
        by (rule indRelST.encR)
    next
      fix S1 S2
      assume "(S1, S2)  SRel"
      thus "SourceTerm S1 ℛ⟦⋅⟧<SRel,TRel> SourceTerm S2"
        by (rule indRelST.source)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      thus "TargetTerm T1 ℛ⟦⋅⟧<SRel,TRel> TargetTerm T2"
        by (rule indRelST.target)
    next
      fix S
      show "TargetTerm (S) ℛ⟦⋅⟧<SRel,TRel> SourceTerm S"
        by (rule indRelST.encL)
    next
      fix S1 S2
      assume "(S1, S2)  SRel"
      with symmS show "SourceTerm S2 ℛ⟦⋅⟧<SRel,TRel> SourceTerm S1"
          unfolding sym_def
        by (simp add: indRelST.source)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      with symmT show "(TargetTerm T2, TargetTerm T1)  indRelST SRel TRel"
          unfolding sym_def
        by (simp add: indRelST.target)
    qed
  qed
  with reflT show "indRelSTEQ SRel TRel = (symcl ((indRelRST SRel TRel)=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelRST SRel TRel"]
            refl_trans_closure_of_indRelST
    by simp
qed

lemma (in encoding) symm_closure_of_indRelLST:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflT: "refl TRel"
      and symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "indRelST SRel TRel = symcl (indRelLST SRel TRel)"
    and "indRelSTEQ SRel TRel = (symcl ((indRelLST SRel TRel)=))+"
proof -
  show "indRelST SRel TRel = symcl (indRelLST SRel TRel)"
  proof auto
    fix P Q
    assume "P ℛ⟦⋅⟧<SRel,TRel> Q"
    thus "(P, Q)  symcl (indRelLST SRel TRel)"
      by (induct, simp_all add: symcl_def indRelLST.intros)
  next
    fix P Q
    assume "(P, Q)  symcl (indRelLST SRel TRel)"
    thus "P ℛ⟦⋅⟧<SRel,TRel> Q"
    proof (auto simp add: symcl_def indRelLST.simps)
      fix S
      show "SourceTerm S ℛ⟦⋅⟧<SRel,TRel> TargetTerm (S)"
        by (rule indRelST.encR)
    next
      fix S1 S2
      assume "(S1, S2)  SRel"
      thus "SourceTerm S1 ℛ⟦⋅⟧<SRel,TRel> SourceTerm S2"
        by (rule indRelST.source)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      thus "TargetTerm T1 ℛ⟦⋅⟧<SRel,TRel> TargetTerm T2"
        by (rule indRelST.target)
    next
      fix S
      show "TargetTerm (S) ℛ⟦⋅⟧<SRel,TRel> SourceTerm S"
        by (rule indRelST.encL)
    next
      fix S1 S2
      assume "(S1, S2)  SRel"
      with symmS show "SourceTerm S2 ℛ⟦⋅⟧<SRel,TRel> SourceTerm S1"
          unfolding sym_def
        by (simp add: indRelST.source)
    next
      fix T1 T2
      assume "(T1, T2)  TRel"
      with symmT show "TargetTerm T2 ℛ⟦⋅⟧<SRel,TRel> TargetTerm T1"
          unfolding sym_def
        by (simp add: indRelST.target)
    qed
  qed
  with reflT show "indRelSTEQ SRel TRel = (symcl ((indRelLST SRel TRel)=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[where Rel="indRelLST SRel TRel"]
            refl_trans_closure_of_indRelST
    by simp
qed

lemma (in encoding) symm_trans_closure_of_indRelRSTPO:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "indRelSTEQ SRel TRel = (symcl (indRelRSTPO SRel TRel))+"
proof auto
  fix P Q
  assume "P ∼⟦⋅⟧<SRel,TRel> Q"
  thus "(P, Q)  (symcl (indRelRSTPO SRel TRel))+"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (symcl (indRelRSTPO SRel TRel))+"
        using indRelRSTPO.encR[of S SRel TRel]
        unfolding symcl_def
      by auto
  next
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (symcl (indRelRSTPO SRel TRel))+"
        using indRelRSTPO.encR[of S SRel TRel]
        unfolding symcl_def
      by auto
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  (symcl (indRelRSTPO SRel TRel))+"
        using indRelRSTPO.source[of S1 S2 SRel TRel]
        unfolding symcl_def
      by auto
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (symcl (indRelRSTPO SRel TRel))+"
        using indRelRSTPO.target[of T1 T2 TRel SRel]
        unfolding symcl_def
      by auto
  next
    case (trans P Q R)
    assume "(P, Q)  (symcl (indRelRSTPO SRel TRel))+"
       and "(Q, R)  (symcl (indRelRSTPO SRel TRel))+"
    thus "(P, R)  (symcl (indRelRSTPO SRel TRel))+"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (symcl (indRelRSTPO SRel TRel))+"
  thus "P ∼⟦⋅⟧<SRel,TRel> Q"
  proof induct
    fix Q
    assume "(P, Q)  symcl (indRelRSTPO SRel TRel)"
    thus "P ∼⟦⋅⟧<SRel,TRel> Q"
    proof (cases "P ≲⟦⋅⟧R<SRel,TRel> Q", simp_all add: symcl_def)
      assume "P ≲⟦⋅⟧R<SRel,TRel> Q"
      thus "P ∼⟦⋅⟧<SRel,TRel> Q"
      proof induct
        case (encR S)
        show "SourceTerm S ∼⟦⋅⟧<SRel,TRel> TargetTerm (S)"
          by (rule indRelSTEQ.encR)
      next
        case (source S1 S2)
        assume "(S1, S2)  SRel"
        thus "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
          by (rule indRelSTEQ.source)
      next
        case (target T1 T2)
        assume "(T1, T2)  TRel"
        thus "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
          by (rule indRelSTEQ.target)
      next
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
    next
      assume "Q ≲⟦⋅⟧R<SRel,TRel> P"
      thus "P ∼⟦⋅⟧<SRel,TRel> Q"
      proof induct
        case (encR S)
        show "TargetTerm (S) ∼⟦⋅⟧<SRel,TRel> SourceTerm S"
          by (rule indRelSTEQ.encL)
      next
        case (source S1 S2)
        assume "(S1, S2)  SRel"
        with symmS show "SourceTerm S2 ∼⟦⋅⟧<SRel,TRel> SourceTerm S1"
            unfolding sym_def
          by (simp add: indRelSTEQ.source)
      next
        case (target T1 T2)
        assume "(T1, T2)  TRel"
        with symmT show "TargetTerm T2 ∼⟦⋅⟧<SRel,TRel> TargetTerm T1"
            unfolding sym_def
          by (simp add: indRelSTEQ.target)
      next
        case (trans P Q R)
        assume "R ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> P"
        thus "R ∼⟦⋅⟧<SRel,TRel> P"
          by (rule indRelSTEQ.trans)
      qed
    qed
  next
    case (step Q R)
    assume "P ∼⟦⋅⟧<SRel,TRel> Q"
    moreover assume "(Q, R)  symcl (indRelRSTPO SRel TRel)"
    hence "Q ∼⟦⋅⟧<SRel,TRel> R"
    proof (auto simp add: symcl_def)
      assume "Q ≲⟦⋅⟧R<SRel,TRel> R"
      thus "Q ∼⟦⋅⟧<SRel,TRel> R"
      proof (induct, simp add: indRelSTEQ.encR, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
    next
      assume "R ≲⟦⋅⟧R<SRel,TRel> Q"
      hence "R ∼⟦⋅⟧<SRel,TRel> Q"
      proof (induct, simp add: indRelSTEQ.encR, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
      with symmS symmT show "Q ∼⟦⋅⟧<SRel,TRel> R"
          using indRelSTEQ_symm[of SRel TRel]
          unfolding sym_def
        by blast
    qed
    ultimately show "P ∼⟦⋅⟧<SRel,TRel> R"
      by (rule indRelSTEQ.trans)
  qed
qed

lemma (in encoding) symm_trans_closure_of_indRelLSTPO:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes symmS: "sym SRel"
      and symmT: "sym TRel"
  shows "indRelSTEQ SRel TRel = (symcl (indRelLSTPO SRel TRel))+"
proof auto
  fix P Q
  assume "P ∼⟦⋅⟧<SRel,TRel> Q"
  thus "(P, Q)  (symcl (indRelLSTPO SRel TRel))+"
  proof induct
    case (encR S)
    show "(SourceTerm S, TargetTerm (S))  (symcl (indRelLSTPO SRel TRel))+"
        using indRelLSTPO.encL[of S SRel TRel]
        unfolding symcl_def
      by blast
  next
    case (encL S)
    show "(TargetTerm (S), SourceTerm S)  (symcl (indRelLSTPO SRel TRel))+"
        using indRelLSTPO.encL[of S SRel TRel]
        unfolding symcl_def
      by blast
  next
    case (source S1 S2)
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  (symcl (indRelLSTPO SRel TRel))+"
        using indRelLSTPO.source[of S1 S2 SRel TRel]
        unfolding symcl_def
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  (symcl (indRelLSTPO SRel TRel))+"
        using indRelLSTPO.target[of T1 T2 TRel SRel]
        unfolding symcl_def
      by blast
  next
    case (trans P Q R)
    assume "(P, Q)  (symcl (indRelLSTPO SRel TRel))+"
       and "(Q, R)  (symcl (indRelLSTPO SRel TRel))+"
    thus "(P, R)  (symcl (indRelLSTPO SRel TRel))+"
      by simp
  qed
next
  fix P Q
  assume "(P, Q)  (symcl (indRelLSTPO SRel TRel))+"
  thus "P ∼⟦⋅⟧<SRel,TRel> Q"
  proof induct
    fix Q
    assume "(P, Q)  symcl (indRelLSTPO SRel TRel)"
    thus "P ∼⟦⋅⟧<SRel,TRel> Q"
      unfolding symcl_def
    proof auto
      assume "P ≲⟦⋅⟧L<SRel,TRel> Q"
      thus "P ∼⟦⋅⟧<SRel,TRel> Q"
      proof (induct, simp add: indRelSTEQ.encL, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
    next
      assume "Q ≲⟦⋅⟧L<SRel,TRel> P"
      hence "Q ∼⟦⋅⟧<SRel,TRel> P"
      proof (induct, simp add: indRelSTEQ.encL, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
      with symmS symmT show "P ∼⟦⋅⟧<SRel,TRel> Q"
          using indRelSTEQ_symm[of SRel TRel]
          unfolding sym_def
        by blast
    qed
  next
    case (step Q R)
    assume "P ∼⟦⋅⟧<SRel,TRel> Q"
    moreover assume "(Q, R)  symcl (indRelLSTPO SRel TRel)"
    hence "Q ∼⟦⋅⟧<SRel,TRel> R"
      unfolding symcl_def
    proof auto
      assume "Q ≲⟦⋅⟧L<SRel,TRel> R"
      thus "Q ∼⟦⋅⟧<SRel,TRel> R"
      proof (induct, simp add: indRelSTEQ.encL, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
    next
      assume "R ≲⟦⋅⟧L<SRel,TRel> Q"
      hence "R ∼⟦⋅⟧<SRel,TRel> Q"
      proof (induct, simp add: indRelSTEQ.encL, simp add: indRelSTEQ.source,
             simp add: indRelSTEQ.target)
        case (trans P Q R)
        assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
        thus "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
      qed
      with symmS symmT show "Q ∼⟦⋅⟧<SRel,TRel> R"
          using indRelSTEQ_symm[of SRel TRel]
          unfolding sym_def
        by blast
    qed
    ultimately show "P ∼⟦⋅⟧<SRel,TRel> R"
      by (rule indRelSTEQ.trans)
  qed
qed

text ‹If the relations indRelRST, indRelLST, or indRelST contain a pair of target terms, then
        this pair is also related by the considered target term relation. Similarly a pair of
        source terms is related by the considered source term relation.›

lemma (in encoding) indRelRST_to_SRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and SP SQ :: "'procS"
  assumes rel: "SourceTerm SP ℛ⟦⋅⟧R<SRel,TRel> SourceTerm SQ"
  shows "(SP, SQ)  SRel"
      using rel
    by (simp add: indRelRST.simps)

lemma (in encoding) indRelRST_to_TRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧R<SRel,TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelRST.simps)

lemma (in encoding) indRelLST_to_SRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and SP SQ :: "'procS"
  assumes rel: "SourceTerm SP ℛ⟦⋅⟧L<SRel,TRel> SourceTerm SQ"
  shows "(SP, SQ)  SRel"
      using rel
    by (simp add: indRelLST.simps)

lemma (in encoding) indRelLST_to_TRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧L<SRel,TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelLST.simps)

lemma (in encoding) indRelST_to_SRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and SP SQ :: "'procS"
  assumes rel: "SourceTerm SP ℛ⟦⋅⟧<SRel,TRel> SourceTerm SQ"
  shows "(SP, SQ)  SRel"
      using rel
    by (simp add: indRelST.simps)

lemma (in encoding) indRelST_to_TRel:
  fixes SRel  :: "('procS × 'procS) set"
    and TRel  :: "('procT × 'procT) set"
    and TP TQ :: "'procT"
  assumes rel: "TargetTerm TP ℛ⟦⋅⟧<SRel,TRel> TargetTerm TQ"
  shows "(TP, TQ)  TRel"
      using rel
    by (simp add: indRelST.simps)

text ‹If the relations indRelRSTPO or indRelLSTPO contain a pair of target terms, then this pair
        is also related by the transitive closure of the considered target term relation. Similarly
        a pair of source terms is related by the transitive closure of the source term relation. A
        pair of a source and a target term results from the combination of pairs in the source
        relation, the target relation, and the encoding function. Note that, because of the
        symmetry, no similar condition holds for indRelSTEQ.›

lemma (in encoding) indRelRSTPO_to_SRel_and_TRel:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes "P ≲⟦⋅⟧R<SRel,TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel+"
    and "SP TQ. SP ∈S P  TQ ∈T Q  (S. (SP, S)  SRel*  (S, TQ)  TRel*)"
    and "TP SQ. TP ∈T P  SQ ∈S Q  False"
    and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
      using assms
proof induct
  case (encR S)
  show "SP SQ. SP ∈S SourceTerm S  SQ ∈S TargetTerm (S)  (SP, SQ)  SRel+"
   and "TP SQ. TP ∈T SourceTerm S  SQ ∈S TargetTerm (S)  False"
   and "TP TQ. TP ∈T SourceTerm S  TQ ∈T TargetTerm (S)  (TP, TQ)  TRel+"
    by simp+
  have "(S, S)  SRel*"
    by simp
  moreover have "(S, S)  TRel*"
    by simp
  ultimately show "SP TQ. SP ∈S SourceTerm S  TQ ∈T TargetTerm (S) 
                   (S. (SP, S)  SRel*  (S, TQ)  TRel*)"
    by blast
next
  case (source S1 S2)
  assume "(S1, S2)  SRel"
  thus "SP SQ. SP ∈S SourceTerm S1  SQ ∈S SourceTerm S2  (SP, SQ)  SRel+"
    by simp
  show "SP TQ. SP ∈S SourceTerm S1  TQ ∈T SourceTerm S2 
        (S. (SP, S)  SRel*  (S, TQ)  TRel*)"
   and "TP SQ. TP ∈T SourceTerm S1  SQ ∈S SourceTerm S2  False"
   and "TP TQ. TP ∈T SourceTerm S1  TQ ∈T SourceTerm S2  (TP, TQ)  TRel+"
    by simp+
next
  case (target T1 T2)
  show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  (SP, SQ)  SRel+"
   and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2
         (S. (SP, S)  SRel*  (S, TQ)  TRel*)"
   and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2  False"
    by simp+
  assume "(T1, T2)  TRel"
  thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2  (TP, TQ)  TRel+"
    by simp
next
  case (trans P Q R)
  assume A1: "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel+"
     and A2: "SP TQ. SP ∈S P  TQ ∈T Q  (S. (SP, S)  SRel*  (S, TQ)  TRel*)"
     and A3: "TP SQ. TP ∈T P  SQ ∈S Q  False"
     and A4: "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
     and A5: "SQ SR. SQ ∈S Q  SR ∈S R  (SQ, SR)  SRel+"
     and A6: "SQ TR. SQ ∈S Q  TR ∈T R  (S. (SQ, S)  SRel*  (S, TR)  TRel*)"
     and A7: "TQ SR. TQ ∈T Q  SR ∈S R  False"
     and A8: "TQ TR. TQ ∈T Q  TR ∈T R  (TQ, TR)  TRel+"
  show "SP SR. SP ∈S P  SR ∈S R  (SP, SR)  SRel+"
  proof clarify
    fix SP SR
    assume A9: "SP ∈S P" and A10: "SR ∈S R"
    show "(SP, SR)  SRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A1 A9 have "(SP, SQ)  SRel+"
        by simp
      moreover from A5 A10 A11 have "(SQ, SR)  SRel+"
        by simp
      ultimately show "(SP, SR)  SRel+"
        by simp
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A7 A10 show "(SP, SR)  SRel+"
        by blast
    qed
  qed
  show "SP TR. SP ∈S P  TR ∈T R
         (S. (SP, S)  SRel*  (S, TR)  TRel*)"
  proof clarify
    fix SP TR
    assume A9: "SP ∈S P" and A10: "TR ∈T R"
    show "S. (SP, S)  SRel*  (S, TR)  TRel*"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A6 A10 obtain S where A12: "(SQ, S)  SRel*"
                             and A13: "(S, TR)  TRel*"
        by blast
      from A1 A9 A11 have "(SP, SQ)  SRel*"
        by simp
      from this A12 have "(SP, S)  SRel*"
        by simp
      with A13 show "S. (SP, S)  SRel*  (S, TR)  TRel*"
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A2 A9 obtain S where A12: "(SP, S)  SRel*"
                            and A13: "(S, TQ)  TRel*"
        by blast
      from A8 A10 A11 have "(TQ, TR)  TRel*"
        by simp
      with A13 have "(S, TR)  TRel*"
        by simp
      with A12 show "S. (SP, S)  SRel*  (S, TR)  TRel*"
        by blast
    qed
  qed
  show "TP SR. TP ∈T P  SR ∈S R  False"
  proof clarify
    fix TP SR
    assume A9: "TP ∈T P" and A10: "SR ∈S R"
    show "False"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 A9 show "False"
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A7 A10 show "False"
        by blast
    qed
  qed
  show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
  proof clarify
    fix TP TR
    assume A9: "TP ∈T P" and A10: "TR ∈T R"
    show "(TP, TR)  TRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A3 A9 show "(TP, TR)  TRel+"
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A4 A9 have "(TP, TQ)  TRel+"
        by simp
      moreover from A8 A10 A11 have "(TQ, TR)  TRel+"
        by simp
      ultimately show "(TP, TR)  TRel+"
        by simp
    qed
  qed
qed

lemma (in encoding) indRelLSTPO_to_SRel_and_TRel:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes "P ≲⟦⋅⟧L<SRel,TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel+"
    and "SP TQ. SP ∈S P  TQ ∈T Q  False"
    and "TP SQ. TP ∈T P  SQ ∈S Q  (S. (TP, S)  TRel*  (S, SQ)  SRel*)"
    and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
      using assms
proof induct
  case (encL S)
  show "SP SQ. SP ∈S TargetTerm (S)  SQ ∈S SourceTerm S  (SP, SQ)  SRel+"
   and "SP TQ. SP ∈S TargetTerm (S)  TQ ∈T SourceTerm S  False"
   and "TP TQ. TP ∈T TargetTerm (S)  TQ ∈T SourceTerm S  (TP, TQ)  TRel+"
    by simp+
  have "(S, S)  TRel*"
    by simp
  moreover have "(S, S)  SRel*"
    by simp
  ultimately show "TP SQ. TP ∈T TargetTerm (S)  SQ ∈S SourceTerm S 
                   (S. (TP, S)  TRel*  (S, SQ)  SRel*)"
    by blast
next
  case (source S1 S2)
  assume "(S1, S2)  SRel"
  thus "SP SQ. SP ∈S SourceTerm S1  SQ ∈S SourceTerm S2  (SP, SQ)  SRel+"
    by simp
  show "SP TQ. SP ∈S SourceTerm S1  TQ ∈T SourceTerm S2  False"
   and "TP SQ. TP ∈T SourceTerm S1  SQ ∈S SourceTerm S2
         (S. (TP, S)  TRel*  (S, SQ)  SRel*)"
   and "TP TQ. TP ∈T SourceTerm S1  TQ ∈T SourceTerm S2  (TP, TQ)  TRel+"
    by simp+
next
  case (target T1 T2)
  show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  (SP, SQ)  SRel+"
   and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2  False"
   and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2
         (S. (TP, S)  TRel*  (S, SQ)  SRel*)"
    by simp+
  assume "(T1, T2)  TRel"
  thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2  (TP, TQ)  TRel+"
    by simp
next
  case (trans P Q R)
  assume A1: "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel+"
     and A2: "SP TQ. SP ∈S P  TQ ∈T Q  False"
     and A3: "TP SQ. TP ∈T P  SQ ∈S Q
               (S. (TP, S)  TRel*  (S, SQ)  SRel*)"
     and A4: "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel+"
     and A5: "SQ SR. SQ ∈S Q  SR ∈S R  (SQ, SR)  SRel+"
     and A6: "SQ TR. SQ ∈S Q  TR ∈T R  False"
     and A7: "TQ SR. TQ ∈T Q  SR ∈S R  (S. (TQ, S)  TRel*  (S, SR)  SRel*)"
     and A8: "TQ TR. TQ ∈T Q  TR ∈T R  (TQ, TR)  TRel+"
  show "SP SR. SP ∈S P  SR ∈S R  (SP, SR)  SRel+"
  proof clarify
    fix SP SR
    assume A9: "SP ∈S P" and A10: "SR ∈S R"
    show "(SP, SR)  SRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A1 A9 have "(SP, SQ)  SRel+"
        by simp
      moreover from A5 A10 A11 have "(SQ, SR)  SRel+"
        by simp
      ultimately show "(SP, SR)  SRel+"
        by simp
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 A9 show "(SP, SR)  SRel+"
        by blast
    qed
  qed
  show "SP TR. SP ∈S P  TR ∈T R  False"
  proof clarify
    fix SP TR
    assume A9: "SP ∈S P" and A10: "TR ∈T R"
    show "False"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A6 A10 show "False"
        by blast
    next
      case (TargetTerm TQ)
      assume "TQ ∈T Q"
      with A2 A9 show "False"
        by blast
    qed
  qed
  show "TP SR. TP ∈T P  SR ∈S R  (S. (TP, S)  TRel*  (S, SR)  SRel*)"
  proof clarify
    fix TP SR
    assume A9: "TP ∈T P" and A10: "SR ∈S R"
    show "S. (TP, S)  TRel*  (S, SR)  SRel*"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A3 A9 obtain S where A12: "(TP, S)  TRel*" and A13: "(S, SQ)  SRel*"
        by blast
      from A5 A10 A11 have "(SQ, SR)  SRel*"
        by simp
      with A13 have "(S, SR)  SRel*"
        by simp
      with A12 show "S. (TP, S)  TRel*  (S, SR)  SRel*"
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A7 A10 obtain S where A12: "(TQ, S)  TRel*" and A13: "(S, SR)  SRel*"
        by blast
      from A4 A9 A11 have "(TP, TQ)  TRel*"
        by simp
      from this A12 have "(TP, S)  TRel*"
        by simp
      with A13 show "S. (TP, S)  TRel*  (S, SR)  SRel*"
        by blast
    qed
  qed
  show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel+"
  proof clarify
    fix TP TR
    assume A9: "TP ∈T P" and A10: "TR ∈T R"
    show "(TP, TR)  TRel+"
    proof (cases Q)
      case (SourceTerm SQ)
      assume "SQ ∈S Q"
      with A6 A10 show "(TP, TR)  TRel+"
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A4 A9 have "(TP, TQ)  TRel+"
        by simp
      moreover from A8 A10 A11 have "(TQ, TR)  TRel+"
        by simp
      ultimately show "(TP, TR)  TRel+"
        by simp
    qed
  qed
qed

text ‹If indRelRSTPO, indRelLSTPO, or indRelSTPO preserves barbs then so do the corresponding
        source term and target term relations.›

lemma (in encoding_wrt_barbs) rel_with_source_impl_SRel_preserves_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes preservation: "rel_preserves_barbs Rel (STCalWB SWB TWB)"
      and sourceInRel:  "S1 S2. (S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  Rel"
  shows "rel_preserves_barbs SRel SWB"
proof clarify
  fix SP SQ a
  assume "(SP, SQ)  SRel"
  with sourceInRel have "(SourceTerm SP, SourceTerm SQ)  Rel"
    by blast
  moreover assume "SP↓<SWB>a"
  hence "SourceTerm SP↓.a"
    by simp
  ultimately have "SourceTerm SQ↓.a"
      using preservation preservation_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "SQ↓<SWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs SRel SWB"
    and "rel_preserves_barbs TRel TWB"
proof -
  show "rel_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_preserves_barbs[where
                          Rel="indRelRSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelRSTPO.source)
next
  show "rel_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_preserves_barbs[where
                          Rel="indRelRSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelRSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs SRel SWB"
    and "rel_preserves_barbs TRel TWB"
proof -
  show "rel_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_preserves_barbs[where
                          Rel="indRelLSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelLSTPO.source)
next
  show "rel_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_preserves_barbs[where
                          Rel="indRelLSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelLSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_preserves_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_preserves_barbs SRel SWB"
    and "rel_preserves_barbs TRel TWB"
proof -
  show "rel_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_preserves_barbs[where
                          Rel="indRelSTEQ SRel TRel" and SRel="SRel"]
    by (simp add: indRelSTEQ.source)
next
  show "rel_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_preserves_barbs[where
                          Rel="indRelSTEQ SRel TRel" and TRel="TRel"]
    by (simp add: indRelSTEQ.target)
qed

lemma (in encoding_wrt_barbs) rel_with_source_impl_SRel_weakly_preserves_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes preservation: "rel_weakly_preserves_barbs Rel (STCalWB SWB TWB)"
      and sourceInRel:  "S1 S2. (S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  Rel"
  shows "rel_weakly_preserves_barbs SRel SWB"
proof clarify
  fix SP SQ a SP'
  assume "(SP, SQ)  SRel"
  with sourceInRel have "(SourceTerm SP, SourceTerm SQ)  Rel"
    by blast
  moreover assume "SP (Calculus SWB)* SP'" and "SP'↓<SWB>a"
  hence "SourceTerm SP⇓.a"
    by blast
  ultimately have "SourceTerm SQ⇓.a"
      using preservation weak_preservation_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "SQ⇓<SWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_weakly_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs SRel SWB"
    and "rel_weakly_preserves_barbs TRel TWB"
proof -
  show "rel_weakly_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_weakly_preserves_barbs[where
                          Rel="indRelRSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelRSTPO.source)
next
  show "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelRSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelRSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_weakly_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs SRel SWB"
    and "rel_weakly_preserves_barbs TRel TWB"
proof -
  show "rel_weakly_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_weakly_preserves_barbs[where
                          Rel="indRelLSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelLSTPO.source)
next
  show "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelLSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelLSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_weakly_preserve_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preservation: "rel_weakly_preserves_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_preserves_barbs SRel SWB"
    and "rel_weakly_preserves_barbs TRel TWB"
proof -
  show "rel_weakly_preserves_barbs SRel SWB"
      using preservation rel_with_source_impl_SRel_weakly_preserves_barbs[where
                          Rel="indRelSTEQ SRel TRel" and SRel="SRel"]
    by (simp add: indRelSTEQ.source)
next
  show "rel_weakly_preserves_barbs TRel TWB"
      using preservation rel_with_target_impl_TRel_weakly_preserves_barbs[where
                          Rel="indRelSTEQ SRel TRel" and TRel="TRel"]
    by (simp add: indRelSTEQ.target)
qed

text ‹If indRelRSTPO, indRelLSTPO, or indRelSTPO reflects barbs then so do the corresponding
        source term and target term relations.›

lemma (in encoding_wrt_barbs) rel_with_source_impl_SRel_reflects_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes reflection: "rel_reflects_barbs Rel (STCalWB SWB TWB)"
      and sourceInRel:  "S1 S2. (S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  Rel"
  shows "rel_reflects_barbs SRel SWB"
proof clarify
  fix SP SQ a
  assume "(SP, SQ)  SRel"
  with sourceInRel have "(SourceTerm SP, SourceTerm SQ)  Rel"
    by blast
  moreover assume "SQ↓<SWB>a"
  hence "SourceTerm SQ↓.a"
    by simp
  ultimately have "SourceTerm SP↓.a"
      using reflection reflection_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "SP↓<SWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs SRel SWB"
    and "rel_reflects_barbs TRel TWB"
proof -
  show "rel_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_reflects_barbs[where
                        Rel="indRelRSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelRSTPO.source)
next
  show "rel_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_reflects_barbs[where
                        Rel="indRelRSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelRSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs SRel SWB"
    and "rel_reflects_barbs TRel TWB"
proof -
  show "rel_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_reflects_barbs[where
                        Rel="indRelLSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelLSTPO.source)
next
  show "rel_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_reflects_barbs[where
                        Rel="indRelLSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelLSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_reflects_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_reflects_barbs SRel SWB"
    and "rel_reflects_barbs TRel TWB"
proof -
  show "rel_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_reflects_barbs[where
                        Rel="indRelSTEQ SRel TRel" and SRel="SRel"]
    by (simp add: indRelSTEQ.source)
next
  show "rel_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_reflects_barbs[where
                        Rel="indRelSTEQ SRel TRel" and TRel="TRel"]
    by (simp add: indRelSTEQ.target)
qed

lemma (in encoding_wrt_barbs) rel_with_source_impl_SRel_weakly_reflects_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes reflection: "rel_weakly_reflects_barbs Rel (STCalWB SWB TWB)"
      and sourceInRel:  "S1 S2. (S1, S2)  SRel  (SourceTerm S1, SourceTerm S2)  Rel"
  shows "rel_weakly_reflects_barbs SRel SWB"
proof clarify
  fix SP SQ a SQ'
  assume "(SP, SQ)  SRel"
  with sourceInRel have "(SourceTerm SP, SourceTerm SQ)  Rel"
    by blast
  moreover assume "SQ (Calculus SWB)* SQ'" and "SQ'↓<SWB>a"
  hence "SourceTerm SQ⇓.a"
    by blast
  ultimately have "SourceTerm SP⇓.a"
      using reflection weak_reflection_of_barbs_in_barbed_encoding[where Rel="Rel"]
    by blast
  thus "SP⇓<SWB>a"
    by simp
qed

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_weakly_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs SRel SWB"
    and "rel_weakly_reflects_barbs TRel TWB"
proof -
  show "rel_weakly_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_weakly_reflects_barbs[where
                        Rel="indRelRSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelRSTPO.source)
next
  show "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                          Rel="indRelRSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelRSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_weakly_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs SRel SWB"
    and "rel_weakly_reflects_barbs TRel TWB"
proof -
  show "rel_weakly_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_weakly_reflects_barbs[where
                        Rel="indRelLSTPO SRel TRel" and SRel="SRel"]
    by (simp add: indRelLSTPO.source)
next
  show "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                        Rel="indRelLSTPO SRel TRel" and TRel="TRel"]
    by (simp add: indRelLSTPO.target)
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_weakly_reflect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes reflection: "rel_weakly_reflects_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_reflects_barbs SRel SWB"
    and "rel_weakly_reflects_barbs TRel TWB"
proof -
  show "rel_weakly_reflects_barbs SRel SWB"
      using reflection rel_with_source_impl_SRel_weakly_reflects_barbs[where
                        Rel="indRelSTEQ SRel TRel" and SRel="SRel"]
    by (simp add: indRelSTEQ.source)
next
  show "rel_weakly_reflects_barbs TRel TWB"
      using reflection rel_with_target_impl_TRel_weakly_reflects_barbs[where
                        Rel="indRelSTEQ SRel TRel" and TRel="TRel"]
    by (simp add: indRelSTEQ.target)
qed

text ‹If indRelRSTPO, indRelLSTPO, or indRelSTPO respects barbs then so do the corresponding
        source term and target term relations.›

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs SRel SWB"
    and "rel_respects_barbs TRel TWB"
proof -
  show "rel_respects_barbs SRel SWB"
      using respection
            indRelRSTPO_impl_SRel_and_TRel_preserve_barbs(1)[where SRel="SRel" and TRel="TRel"]
            indRelRSTPO_impl_SRel_and_TRel_reflect_barbs(1)[where SRel="SRel" and TRel="TRel"]
    by blast
next
  show "rel_respects_barbs TRel TWB"
      using respection
            indRelRSTPO_impl_SRel_and_TRel_preserve_barbs(2)[where SRel="SRel" and TRel="TRel"]
            indRelRSTPO_impl_SRel_and_TRel_reflect_barbs(2)[where SRel="SRel" and TRel="TRel"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs SRel SWB"
    and "rel_respects_barbs TRel TWB"
proof -
  show "rel_respects_barbs SRel SWB"
      using respection
            indRelLSTPO_impl_SRel_and_TRel_preserve_barbs(1)[where SRel="SRel" and TRel="TRel"]
            indRelLSTPO_impl_SRel_and_TRel_reflect_barbs(1)[where SRel="SRel" and TRel="TRel"]
    by blast
next
  show "rel_respects_barbs TRel TWB"
      using respection
            indRelLSTPO_impl_SRel_and_TRel_preserve_barbs(2)[where SRel="SRel" and TRel="TRel"]
            indRelLSTPO_impl_SRel_and_TRel_reflect_barbs(2)[where SRel="SRel" and TRel="TRel"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_respects_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_respects_barbs SRel SWB"
    and "rel_respects_barbs TRel TWB"
proof -
  show "rel_respects_barbs SRel SWB"
      using respection
            indRelSTEQ_impl_SRel_and_TRel_preserve_barbs(1)[where SRel="SRel" and TRel="TRel"]
            indRelSTEQ_impl_SRel_and_TRel_reflect_barbs(1)[where SRel="SRel" and TRel="TRel"]
    by blast
next
  show "rel_respects_barbs TRel TWB"
      using respection
            indRelSTEQ_impl_SRel_and_TRel_preserve_barbs(2)[where SRel="SRel" and TRel="TRel"]
            indRelSTEQ_impl_SRel_and_TRel_reflect_barbs(2)[where SRel="SRel" and TRel="TRel"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelRSTPO_impl_SRel_and_TRel_weakly_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelRSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs SRel SWB"
    and "rel_weakly_respects_barbs TRel TWB"
proof -
  show "rel_weakly_respects_barbs SRel SWB"
      using respection indRelRSTPO_impl_SRel_and_TRel_weakly_preserve_barbs(1)[where SRel="SRel"
                        and TRel="TRel"]
            indRelRSTPO_impl_SRel_and_TRel_weakly_reflect_barbs(1)[where SRel="SRel"
              and TRel="TRel"]
    by blast
next
  show "rel_weakly_respects_barbs TRel TWB"
      using respection indRelRSTPO_impl_SRel_and_TRel_weakly_preserve_barbs(2)[where SRel="SRel"
                        and TRel="TRel"]
            indRelRSTPO_impl_SRel_and_TRel_weakly_reflect_barbs(2)[where SRel="SRel"
              and TRel="TRel"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelLSTPO_impl_SRel_and_TRel_weakly_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelLSTPO SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs SRel SWB"
    and "rel_weakly_respects_barbs TRel TWB"
proof -
  show "rel_weakly_respects_barbs SRel SWB"
      using respection indRelLSTPO_impl_SRel_and_TRel_weakly_preserve_barbs(1)[where SRel="SRel"
                        and TRel="TRel"]
            indRelLSTPO_impl_SRel_and_TRel_weakly_reflect_barbs(1)[where SRel="SRel"
              and TRel="TRel"]
    by blast
next
  show "rel_weakly_respects_barbs TRel TWB"
      using respection indRelLSTPO_impl_SRel_and_TRel_weakly_preserve_barbs(2)[where SRel="SRel"
                        and TRel="TRel"]
            indRelLSTPO_impl_SRel_and_TRel_weakly_reflect_barbs(2)[where SRel="SRel"
              and TRel="TRel"]
    by blast
qed

lemma (in encoding_wrt_barbs) indRelSTEQ_impl_SRel_and_TRel_weakly_respect_barbs:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes respection: "rel_weakly_respects_barbs (indRelSTEQ SRel TRel) (STCalWB SWB TWB)"
  shows "rel_weakly_respects_barbs SRel SWB"
    and "rel_weakly_respects_barbs TRel TWB"
proof -
  show "rel_weakly_respects_barbs SRel SWB"
      using respection indRelSTEQ_impl_SRel_and_TRel_weakly_preserve_barbs(1)[where SRel="SRel"
                        and TRel="TRel"]
            indRelSTEQ_impl_SRel_and_TRel_weakly_reflect_barbs(1)[where SRel="SRel"
              and TRel="TRel"]
    by blast
next
  show "rel_weakly_respects_barbs TRel TWB"
      using respection indRelSTEQ_impl_SRel_and_TRel_weakly_preserve_barbs(2)[where SRel="SRel"
                        and TRel="TRel"]
            indRelSTEQ_impl_SRel_and_TRel_weakly_reflect_barbs(2)[where SRel="SRel"
              and TRel="TRel"]
    by blast
qed

text ‹If TRel is reflexive then ind relRTPO is a subrelation of indRelTEQ. If SRel is reflexive
        then indRelRTPO is a subrelation of indRelRTPO. Moreover, indRelRSTPO is a subrelation of
        indRelSTEQ.›

lemma (in encoding) indRelRTPO_to_indRelTEQ:
  fixes TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel:   "P ≲⟦⋅⟧RT<TRel> Q"
      and reflT: "refl TRel"
  shows "P ∼⟦⋅⟧T<TRel> Q"
    using rel
proof induct
  case (encR S)
  show "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
    by (rule indRelTEQ.encR)
next
  case (source S)
  from reflT show "SourceTerm S ∼⟦⋅⟧T<TRel> SourceTerm S"
      using indRelTEQ_refl[of TRel]
      unfolding refl_on_def
    by simp
next
  case (target T1 T2)
  assume "(T1, T2)  TRel"
  thus "TargetTerm T1 ∼⟦⋅⟧T<TRel> TargetTerm T2"
    by (rule indRelTEQ.target)
next
  case (trans TP TQ TR)
  assume "TP ∼⟦⋅⟧T<TRel> TQ" and "TQ ∼⟦⋅⟧T<TRel> TR"
  thus "TP ∼⟦⋅⟧T<TRel> TR"
    by (rule indRelTEQ.trans)
qed

lemma (in encoding) indRelRTPO_to_indRelRSTPO:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel:   "P ≲⟦⋅⟧RT<TRel> Q"
      and reflS: "refl SRel"
  shows "P ≲⟦⋅⟧R<SRel,TRel> Q"
    using rel
proof induct
  case (encR S)
  show "SourceTerm S ≲⟦⋅⟧R<SRel,TRel> TargetTerm (S)"
    by (rule indRelRSTPO.encR)
next
  case (source S)
  from reflS show "SourceTerm S ≲⟦⋅⟧R<SRel,TRel> SourceTerm S"
      unfolding refl_on_def
    by (simp add: indRelRSTPO.source)
next
  case (target T1 T2)
  assume "(T1, T2)  TRel"
  thus "TargetTerm T1 ≲⟦⋅⟧R<SRel,TRel> TargetTerm T2"
    by (rule indRelRSTPO.target)
next
  case (trans P Q R)
  assume "P ≲⟦⋅⟧R<SRel,TRel> Q" and "Q ≲⟦⋅⟧R<SRel,TRel> R"
  thus "P ≲⟦⋅⟧R<SRel,TRel> R"
    by (rule indRelRSTPO.trans)
qed

lemma (in encoding) indRelRSTPO_to_indRelSTEQ:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes rel: "P ≲⟦⋅⟧R<SRel,TRel> Q"
  shows "P ∼⟦⋅⟧<SRel,TRel> Q"
    using rel
proof induct
  case (encR S)
  show "SourceTerm S ∼⟦⋅⟧<SRel,TRel> TargetTerm (S)"
    by (rule indRelSTEQ.encR)
next
  case (source S1 S2)
  assume "(S1, S2)  SRel"
  thus "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
    by (rule indRelSTEQ.source)
next
  case (target T1 T2)
  assume "(T1, T2)  TRel"
  thus "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
    by (rule indRelSTEQ.target)
next
  case (trans P Q R)
  assume "P ∼⟦⋅⟧<SRel,TRel> Q" and "Q ∼⟦⋅⟧<SRel,TRel> R"
  thus "P ∼⟦⋅⟧<SRel,TRel> R"
    by (rule indRelSTEQ.trans)
qed

text ‹If indRelRTPO is a bisimulation and SRel is a reflexive bisimulation then also indRelRSTPO
        is a bisimulation.›

lemma (in encoding) indRelRTPO_weak_reduction_bisimulation_impl_indRelRSTPO_bisimulation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes bisimT: "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      and bisimS: "weak_reduction_bisimulation SRel Source"
      and reflS:  "refl SRel"
  shows "weak_reduction_bisimulation (indRelRSTPO SRel TRel) (STCal Source Target)"
proof auto
  fix P Q P'
  assume "P ≲⟦⋅⟧R<SRel,TRel> Q" and "P (STCal Source Target)* P'"
  thus "Q'. Q (STCal Source Target)* Q'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
  proof (induct arbitrary: P')
    case (encR S)
    have "SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
      by (rule indRelRTPO.encR)
    moreover assume "SourceTerm S (STCal Source Target)* P'"
    ultimately obtain Q' where A1: "TargetTerm (S) (STCal Source Target)* Q'"
                           and A2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        using bisimT
      by blast
    from reflS A2 have "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by (simp add: indRelRTPO_to_indRelRSTPO)
    with A1 show "Q'. TargetTerm (S) (STCal Source Target)* Q'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (source S1 S2)
    assume "SourceTerm S1 (STCal Source Target)* P'"
    from this obtain S1' where B1: "S1' ∈S P'" and B2: "S1 Source* S1'"
      by (auto simp add: STCal_steps(1))
    assume "(S1, S2)  SRel"
    with B2 bisimS obtain S2' where B3: "S2 Source* S2'" and B4: "(S1', S2')  SRel"
      by blast
    from B3 have "SourceTerm S2 (STCal Source Target)* (SourceTerm S2')"
      by (simp add: STCal_steps(1))
    moreover from B1 B4 have "P' ≲⟦⋅⟧R<SRel,TRel> SourceTerm S2'"
      by (simp add: indRelRSTPO.source)
    ultimately show "Q'. SourceTerm S2 (STCal Source Target)* Q'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    hence "TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
      by (rule indRelRTPO.target)
    moreover assume "TargetTerm T1 (STCal Source Target)* P'"
    ultimately obtain Q' where C1: "TargetTerm T2 (STCal Source Target)* Q'"
                           and C2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        using bisimT
      by blast
    from reflS C2 have "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by (simp add: indRelRTPO_to_indRelRSTPO)
    with C1 show "Q'. TargetTerm T2 (STCal Source Target)* Q'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (trans P Q R)
    assume "P (STCal Source Target)* P'"
       and "P'. P (STCal Source Target)* P'
             Q'. Q (STCal Source Target)* Q'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
    from this obtain Q' where D1: "Q (STCal Source Target)* Q'" and D2: "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
    assume "Q'. Q (STCal Source Target)* Q'
             R'. R (STCal Source Target)* R'  Q' ≲⟦⋅⟧R<SRel,TRel> R'"
    with D1 obtain R' where D3: "R (STCal Source Target)* R'" and D4: "Q' ≲⟦⋅⟧R<SRel,TRel> R'"
      by blast
    from D2 D4 have "P' ≲⟦⋅⟧R<SRel,TRel> R'"
      by (rule indRelRSTPO.trans)
    with D3 show "R'. R (STCal Source Target)* R'  P' ≲⟦⋅⟧R<SRel,TRel> R'"
      by blast
  qed
next
  fix P Q Q'
  assume "P ≲⟦⋅⟧R<SRel,TRel> Q" and "Q (STCal Source Target)* Q'"
  thus "P'. P (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
  proof (induct arbitrary: Q')
    case (encR S)
    have "SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
      by (rule indRelRTPO.encR)
    moreover assume "TargetTerm (S) (STCal Source Target)* Q'"
    ultimately obtain P' where E1: "SourceTerm S (STCal Source Target)* P'"
                           and E2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        using bisimT
      by blast
    from reflS E2 have "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by (simp add: indRelRTPO_to_indRelRSTPO)
    with E1 show "P'. SourceTerm S (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (source S1 S2)
    assume "SourceTerm S2 (STCal Source Target)* Q'"
    from this obtain S2' where F1: "S2' ∈S Q'" and F2: "S2 Source* S2'"
      by (auto simp add: STCal_steps(1))
    assume "(S1, S2)  SRel"
    with F2 bisimS obtain S1' where F3: "S1 Source* S1'" and F4: "(S1', S2')  SRel"
      by blast
    from F3 have "SourceTerm S1 (STCal Source Target)* (SourceTerm S1')"
      by (simp add: STCal_steps(1))
    moreover from F1 F4 have "SourceTerm S1' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by (simp add: indRelRSTPO.source)
    ultimately show "P'. SourceTerm S1 (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    hence "TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
      by (rule indRelRTPO.target)
    moreover assume "TargetTerm T2 (STCal Source Target)* Q'"
    ultimately obtain P' where G1: "TargetTerm T1 (STCal Source Target)* P'"
                           and G2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        using bisimT
      by blast
    from reflS G2 have "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by (simp add: indRelRTPO_to_indRelRSTPO)
    with G1 show "P'. TargetTerm T1 (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
  next
    case (trans P Q R R')
    assume "R (STCal Source Target)* R'"
       and "R'. R (STCal Source Target)* R'
             Q'. Q (STCal Source Target)* Q'  Q' ≲⟦⋅⟧R<SRel,TRel> R'"
    from this obtain Q' where H1: "Q (STCal Source Target)* Q'" and H2: "Q' ≲⟦⋅⟧R<SRel,TRel> R'"
      by blast
    assume "Q'. Q (STCal Source Target)* Q'
             P'. P (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> Q'"
    with H1 obtain P' where H3: "P (STCal Source Target)* P'" and H4: "P' ≲⟦⋅⟧R<SRel,TRel> Q'"
      by blast
    from H4 H2 have "P' ≲⟦⋅⟧R<SRel,TRel> R'"
      by (rule indRelRSTPO.trans)
    with H3 show "P'. P (STCal Source Target)* P'  P' ≲⟦⋅⟧R<SRel,TRel> R'"
      by blast
  qed
qed

end

Theory SuccessSensitiveness

theory SuccessSensitiveness
  imports SourceTargetRelation
begin

section ‹Success Sensitiveness and Barbs›

text ‹To compare the abstract behavior of two terms, often some notion of success or successful
        termination is used. Daniele Gorla assumes a constant process (similar to the empty
        process) that represents successful termination in order to compare the behavior of source
        terms with their literal translations. Then an encoding is success sensitive if, for all
        source terms S, S reaches success iff the translation of S reaches success. Successful
        termination can be considered as some special kind of barb. Accordingly we generalize
        successful termination to the respection of an arbitrary subset of barbs. An encoding
        respects a set of barbs if, for every source term S and all considered barbs a, S reaches a
        iff the translation of S reaches a.›

abbreviation (in encoding_wrt_barbs) enc_weakly_preserves_barb_set :: "'barbs set  bool" where
  "enc_weakly_preserves_barb_set Barbs  enc_preserves_binary_pred (λP a. a  Barbs  P⇓.a)"

abbreviation (in encoding_wrt_barbs) enc_weakly_preserves_barbs :: "bool" where
  "enc_weakly_preserves_barbs  enc_preserves_binary_pred (λP a. P⇓.a)"

lemma (in encoding_wrt_barbs) enc_weakly_preserves_barbs_and_barb_set:
  shows "enc_weakly_preserves_barbs = (Barbs. enc_weakly_preserves_barb_set Barbs)"
    by blast

abbreviation (in encoding_wrt_barbs) enc_weakly_reflects_barb_set :: "'barbs set  bool" where
  "enc_weakly_reflects_barb_set Barbs  enc_reflects_binary_pred (λP a. a  Barbs  P⇓.a)"

abbreviation (in encoding_wrt_barbs) enc_weakly_reflects_barbs :: "bool" where
  "enc_weakly_reflects_barbs  enc_reflects_binary_pred (λP a. P⇓.a)"

lemma (in encoding_wrt_barbs) enc_weakly_reflects_barbs_and_barb_set:
  shows "enc_weakly_reflects_barbs = (Barbs. enc_weakly_reflects_barb_set Barbs)"
    by blast

abbreviation (in encoding_wrt_barbs) enc_weakly_respects_barb_set :: "'barbs set  bool" where
  "enc_weakly_respects_barb_set Barbs 
   enc_weakly_preserves_barb_set Barbs  enc_weakly_reflects_barb_set Barbs"

abbreviation (in encoding_wrt_barbs) enc_weakly_respects_barbs :: "bool" where
  "enc_weakly_respects_barbs  enc_weakly_preserves_barbs  enc_weakly_reflects_barbs"

lemma (in encoding_wrt_barbs) enc_weakly_respects_barbs_and_barb_set:
  shows "enc_weakly_respects_barbs = (Barbs. enc_weakly_respects_barb_set Barbs)"
proof -
  have "(Barbs. enc_weakly_respects_barb_set Barbs)
        = (Barbs. (S x. x  Barbs  S⇓<SWB>x  S⇓<TWB>x)
           (S x. x  Barbs  S⇓<TWB>x  S⇓<SWB>x))"
    by simp
  hence "(Barbs. enc_weakly_respects_barb_set Barbs)
        = ((Barbs. enc_weakly_preserves_barb_set Barbs)
             (Barbs. enc_weakly_reflects_barb_set Barbs))"
    apply simp by fast
  thus ?thesis
    apply simp by blast
qed

text ‹An encoding strongly respects some set of barbs if, for every source term S and all
        considered barbs a, S has a iff the translation of S has a.›

abbreviation (in encoding_wrt_barbs) enc_preserves_barb_set :: "'barbs set  bool" where
  "enc_preserves_barb_set Barbs  enc_preserves_binary_pred (λP a. a  Barbs  P↓.a)"

abbreviation (in encoding_wrt_barbs) enc_preserves_barbs :: "bool" where
  "enc_preserves_barbs  enc_preserves_binary_pred (λP a. P↓.a)"

lemma (in encoding_wrt_barbs) enc_preserves_barbs_and_barb_set:
  shows "enc_preserves_barbs = (Barbs. enc_preserves_barb_set Barbs)"
    by blast

abbreviation (in encoding_wrt_barbs) enc_reflects_barb_set :: "'barbs set  bool" where
  "enc_reflects_barb_set Barbs  enc_reflects_binary_pred (λP a. a  Barbs  P↓.a)"

abbreviation (in encoding_wrt_barbs) enc_reflects_barbs :: "bool" where
  "enc_reflects_barbs  enc_reflects_binary_pred (λP a. P↓.a)"

lemma (in encoding_wrt_barbs) enc_reflects_barbs_and_barb_set:
  shows "enc_reflects_barbs = (Barbs. enc_reflects_barb_set Barbs)"
    by blast

abbreviation (in encoding_wrt_barbs) enc_respects_barb_set :: "'barbs set  bool" where
  "enc_respects_barb_set Barbs  enc_preserves_barb_set Barbs  enc_reflects_barb_set Barbs"

abbreviation (in encoding_wrt_barbs) enc_respects_barbs :: "bool" where
  "enc_respects_barbs  enc_preserves_barbs  enc_reflects_barbs"

lemma (in encoding_wrt_barbs) enc_respects_barbs_and_barb_set:
  shows "enc_respects_barbs = (Barbs. enc_respects_barb_set Barbs)"
proof -
  have "(Barbs. enc_respects_barb_set Barbs)
        = ((Barbs. enc_preserves_barb_set Barbs)
             (Barbs. enc_reflects_barb_set Barbs))"
    apply simp by fast
  thus ?thesis
    apply simp by blast
qed

text ‹An encoding (weakly) preserves barbs iff
        (1) there exists a relation, like indRelR, that relates source terms and their literal
            translations and preserves (reachability/)existence of barbs, or
        (2) there exists a relation, like indRelL, that relates literal translations and their
            source terms and reflects (reachability/)existence of barbs.›

lemma (in encoding_wrt_barbs) enc_weakly_preserves_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
    and TRel  :: "('procT × 'procT) set"
  shows "enc_weakly_preserves_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_preserves_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_preserves_binary_pred_iff_source_target_rel_preserves_binary_pred[where
             Pred="λP a. a  Barbs  P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_weakly_preserves_barbs_iff_source_target_rel:
  shows "enc_weakly_preserves_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_preserves_barbs Rel (STCalWB SWB TWB))"
      using enc_preserves_binary_pred_iff_source_target_rel_preserves_binary_pred[where
             Pred="λP a. P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_preserves_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
  shows "enc_preserves_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_preserves_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_preserves_binary_pred_iff_source_target_rel_preserves_binary_pred[where
             Pred="λP a. a  Barbs  P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_preserves_barbs_iff_source_target_rel:
  shows "enc_preserves_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_preserves_barbs Rel (STCalWB SWB TWB))"
      using enc_preserves_binary_pred_iff_source_target_rel_preserves_binary_pred[where
             Pred="λP a. P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

text ‹An encoding (weakly) reflects barbs iff
        (1) there exists a relation, like indRelR, that relates source terms and their literal
            translations and reflects (reachability/)existence of barbs, or
        (2) there exists a relation, like indRelL, that relates literal translations and their
            source terms and preserves (reachability/)existence of barbs.›

lemma (in encoding_wrt_barbs) enc_weakly_reflects_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
  shows "enc_weakly_reflects_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_reflects_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_reflects_binary_pred_iff_source_target_rel_reflects_binary_pred[where
             Pred="λP a. a  Barbs  P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_weakly_reflects_barbs_iff_source_target_rel:
  shows "enc_weakly_reflects_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_reflects_barbs Rel (STCalWB SWB TWB))"
      using enc_reflects_binary_pred_iff_source_target_rel_reflects_binary_pred[where
             Pred="λP a. P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_reflects_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
  shows "enc_reflects_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_reflects_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_reflects_binary_pred_iff_source_target_rel_reflects_binary_pred[where
             Pred="λP a. a  Barbs  P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_reflects_barbs_iff_source_target_rel:
  shows "enc_reflects_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_reflects_barbs Rel (STCalWB SWB TWB))"
      using enc_reflects_binary_pred_iff_source_target_rel_reflects_binary_pred[where
             Pred="λP a. P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

text ‹An encoding (weakly) respects barbs iff
        (1) there exists a relation, like indRelR, that relates source terms and their literal
            translations and respects (reachability/)existence of barbs, or
        (2) there exists a relation, like indRelL, that relates literal translations and their
            source terms and respects (reachability/)existence of barbs, or
        (3) there exists a relation, like indRel, that relates source terms and their literal
            translations in both directions and respects (reachability/)existence of barbs.›

lemma (in encoding_wrt_barbs) enc_weakly_respects_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
  shows "enc_weakly_respects_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_respects_binary_pred_iff_source_target_rel_respects_binary_pred_encR[where
             Pred="λP a. a  Barbs  P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_weakly_respects_barbs_iff_source_target_rel:
  shows "enc_weakly_respects_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_respects_barbs Rel (STCalWB SWB TWB))"
      using enc_respects_binary_pred_iff_source_target_rel_respects_binary_pred_encR[where
             Pred="λP a. P⇓<STCalWB SWB TWB>a"] STCalWB_reachesBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_respects_barb_set_iff_source_target_rel:
  fixes Barbs :: "'barbs set"
  shows "enc_respects_barb_set Barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_respects_barb_set Rel (STCalWB SWB TWB) Barbs)"
      using enc_respects_binary_pred_iff_source_target_rel_respects_binary_pred_encR[where
             Pred="λP a. a  Barbs  P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

lemma (in encoding_wrt_barbs) enc_respects_barbs_iff_source_target_rel:
  shows "enc_respects_barbs
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_respects_barbs Rel (STCalWB SWB TWB))"
      using enc_respects_binary_pred_iff_source_target_rel_respects_binary_pred_encR[where
             Pred="λP a. P↓<STCalWB SWB TWB>a"] STCalWB_hasBarbST
    by simp

text ‹Accordingly an encoding is success sensitive iff there exists such a relation between
        source and target terms that weakly respects the barb success.›

lemma (in encoding_wrt_barbs) success_sensitive_cond:
  fixes success :: "'barbs"
  shows "enc_weakly_respects_barb_set {success} = (S. S⇓<SWB>success  S⇓<TWB>success)"
    by auto

lemma (in encoding_wrt_barbs) success_sensitive_iff_source_target_rel_weakly_respects_success:
  fixes success :: "'barbs"
  shows "enc_weakly_respects_barb_set {success}
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
    by (rule enc_weakly_respects_barb_set_iff_source_target_rel[where Barbs="{success}"])+

lemma (in encoding_wrt_barbs) success_sensitive_iff_source_target_rel_respects_success:
  fixes success :: "'barbs"
  shows "enc_respects_barb_set {success}
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_respects_barb_set Rel (STCalWB SWB TWB) {success})"
    by (rule enc_respects_barb_set_iff_source_target_rel[where Barbs="{success}"])

end

Theory DivergenceReflection

theory DivergenceReflection
  imports SourceTargetRelation
begin

section ‹Divergence Reflection›

text ‹Divergence reflection forbids for encodings that introduce loops of internal actions. Thus
        they determine the practicability of encodings in particular with respect to
        implementations. An encoding reflects divergence if each loop in a target term result from
        the translation of a divergent source term.›

abbreviation (in encoding) enc_preserves_divergence :: "bool" where
  "enc_preserves_divergence  enc_preserves_pred (λP. P ⟼STω)"

lemma (in encoding) divergence_preservation_cond:
  shows "enc_preserves_divergence = (S. S (Source)ω  S (Target)ω)"
    by simp

abbreviation (in encoding) enc_reflects_divergence :: "bool" where
  "enc_reflects_divergence  enc_reflects_pred (λP. P ⟼STω)"

lemma (in encoding) divergence_reflection_cond:
  shows "enc_reflects_divergence = (S. S (Target)ω  S (Source)ω)"
    by simp

abbreviation rel_preserves_divergence
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "rel_preserves_divergence Rel Cal  rel_preserves_pred Rel (λP. P (Cal)ω)"

abbreviation rel_reflects_divergence
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "rel_reflects_divergence Rel Cal  rel_reflects_pred Rel (λP. P (Cal)ω)"

text ‹Apart from divergence reflection we consider divergence respection. An encoding respects
        divergence if each divergent source term is translated into a divergent target term and
        each divergent target term result from the translation of a divergent source term.›

abbreviation (in encoding) enc_respects_divergence :: "bool" where
  "enc_respects_divergence  enc_respects_pred (λP. P ⟼STω)"

lemma (in encoding) divergence_respection_cond:
  shows "enc_respects_divergence = (S. S (Target)ω  S (Source)ω)"
    by auto

abbreviation rel_respects_divergence
    :: "('proc × 'proc) set  'proc processCalculus  bool"
  where
  "rel_respects_divergence Rel Cal  rel_respects_pred Rel (λP. P (Cal)ω)"

text ‹An encoding preserves divergence iff
        (1) there exists a relation that relates source terms and their literal translations and
            preserves divergence, or
        (2) there exists a relation that relates literal translations and their source terms and
            reflects divergence.›

lemma (in encoding) divergence_preservation_iff_source_target_rel_preserves_divergence:
  shows "enc_preserves_divergence
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_preserves_divergence Rel (STCal Source Target))"
      using enc_preserves_pred_iff_source_target_rel_preserves_pred(1)[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp

lemma (in encoding) divergence_preservation_iff_source_target_rel_reflects_divergence:
  shows "enc_preserves_divergence
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)
             rel_reflects_divergence Rel (STCal Source Target))"
      using enc_preserves_pred_iff_source_target_rel_reflects_pred(1)[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp

text ‹An encoding reflects divergence iff
        (1) there exists a relation that relates source terms and their literal translations and
            reflects divergence, or
        (2) there exists a relation that relates literal translations and their source terms and
            preserves divergence.›

lemma (in encoding) divergence_reflection_iff_source_target_rel_reflects_divergence:
  shows "enc_reflects_divergence
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_reflects_divergence Rel (STCal Source Target))"
      using enc_reflects_pred_iff_source_target_rel_reflects_pred[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp

lemma (in encoding) divergence_reflection_iff_source_target_rel_preserves_divergence:
  shows "enc_reflects_divergence
         = (Rel. (S. (TargetTerm (S), SourceTerm S)  Rel)
             rel_preserves_divergence Rel (STCal Source Target))"
      using enc_reflects_pred_iff_source_target_rel_preserves_pred[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp

text ‹An encoding respects divergence iff there exists a relation that relates source terms and
        their literal translations in both directions and respects divergence.›

lemma (in encoding) divergence_respection_iff_source_target_rel_respects_divergence:
  shows "enc_respects_divergence = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          rel_respects_divergence Rel (STCal Source Target))"
  and   "enc_respects_divergence = (Rel.
         (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          rel_respects_divergence Rel (STCal Source Target))"
proof -
  show "enc_respects_divergence = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         rel_respects_divergence Rel (STCal Source Target))"
      using enc_respects_pred_iff_source_target_rel_respects_pred_encR[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp
next
  show "enc_respects_divergence = (Rel.
        (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
         rel_respects_divergence Rel (STCal Source Target))"
      using enc_respects_pred_iff_source_target_rel_respects_pred_encRL[where Pred="λP. P ⟼STω"]
            divergentST_STCal_divergent
    by simp
qed

end

Theory OperationalCorrespondence

theory OperationalCorrespondence
  imports SourceTargetRelation
begin

section ‹Operational Correspondence›

text ‹We consider different variants of operational correspondence. This criterion consists of a
        completeness and a soundness condition and is often defined with respect to a relation TRel
        on target terms. Operational completeness modulo TRel ensures that an encoding preserves
        source term behaviour modulo TRel by requiring that each sequence of source term steps can
        be mimicked by its translation such that the respective derivatives are related by TRel.›

abbreviation (in encoding) operational_complete :: "('procT × 'procT) set  bool" where
  "operational_complete TRel 
   S S'. S Source* S'  (T. S Target* T  (S', T)  TRel)"

text ‹We call an encoding strongly operational complete modulo TRel if each source term step has
        to be mimicked by single target term step of its translation.›

abbreviation (in encoding) strongly_operational_complete :: "('procT × 'procT) set  bool" where
  "strongly_operational_complete TRel 
   S S'. S Source S'  (T. S Target T  (S', T)  TRel)"

text ‹Operational soundness ensures that the encoding does not introduce new behaviour. An
        encoding is weakly operational sound modulo TRel if each sequence of target term steps is
        part of the translation of a sequence of source term steps such that the derivatives are
        related by TRel. It allows for intermediate states on the translation of source term step
        that are not the result of translating a source term.›

abbreviation (in encoding) weakly_operational_sound :: "('procT × 'procT) set  bool" where
  "weakly_operational_sound TRel 
   S T. S Target* T  (S' T'. S Source* S'  T Target* T'  (S', T')  TRel)"

text ‹And encoding is operational sound modulo TRel if each sequence of target term steps is the
        translation of a sequence of source term steps such that the derivatives are related by
        TRel. This criterion does not allow for intermediate states, i.e., does not allow to a
        reach target term from an encoded source term that is not related by TRel to the
        translation of a source term.›

abbreviation (in encoding) operational_sound :: "('procT × 'procT) set  bool" where
  "operational_sound TRel  S T. S Target* T  (S'. S Source* S'  (S', T)  TRel)"

text ‹Strong operational soundness modulo TRel is a stricter variant of operational soundness,
        where a single target term step has to be mapped on a single source term step.›

abbreviation (in encoding) strongly_operational_sound :: "('procT × 'procT) set  bool" where
  "strongly_operational_sound TRel 
   S T. S Target T  (S'. S Source S'  (S', T)  TRel)"

text ‹An encoding is weakly operational corresponding modulo TRel if it is operational complete
        and weakly operational sound modulo TRel.›

abbreviation (in encoding) weakly_operational_corresponding
    :: "('procT × 'procT) set  bool"
  where
  "weakly_operational_corresponding TRel 
   operational_complete TRel  weakly_operational_sound TRel"

text ‹Operational correspondence modulo is the combination of operational completeness and
        operational soundness modulo TRel.›

abbreviation (in encoding) operational_corresponding :: "('procT × 'procT) set  bool" where
  "operational_corresponding TRel  operational_complete TRel  operational_sound TRel"

text ‹An encoding is strongly operational corresponding modulo TRel if it is strongly operational
        complete and strongly operational sound modulo TRel.›

abbreviation (in encoding) strongly_operational_corresponding
    :: "('procT × 'procT) set  bool"
  where
  "strongly_operational_corresponding TRel 
   strongly_operational_complete TRel  strongly_operational_sound TRel"

subsection ‹Trivial Operational Correspondence Results›

text ‹Every encoding is (weakly) operational corresponding modulo the all relation on target
        terms.›

lemma (in encoding) operational_correspondence_modulo_all_relation:
  shows "operational_complete {(T1, T2). True}"
    and "weakly_operational_sound {(T1, T2). True}"
    and "operational_sound {(T1, T2). True}"
      using steps_refl[where Cal="Source"] steps_refl[where Cal="Target"]
    by blast+

lemma all_relation_is_weak_reduction_bisimulation:
  fixes Cal :: "'a processCalculus"
  shows "weak_reduction_bisimulation {(a, b). True} Cal"
      using steps_refl[where Cal="Cal"]
    by blast

lemma (in encoding) operational_correspondence_modulo_some_target_relation:
  shows "TRel. weakly_operational_corresponding TRel"
    and "TRel. operational_corresponding TRel"
    and "TRel. weakly_operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
    and "TRel. operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
      using operational_correspondence_modulo_all_relation
            all_relation_is_weak_reduction_bisimulation[where Cal="Target"]
    by blast+

text ‹Strong operational correspondence requires that source can perform a step iff their
        translations can perform a step.›

lemma (in encoding) strong_operational_correspondence_modulo_some_target_relation:
  shows "(TRel. strongly_operational_corresponding TRel)
         = (S. (S'. S Source S')  (T. S Target T))"
    and "(TRel. strongly_operational_corresponding TRel
           weak_reduction_bisimulation TRel Target)
         = (S. (S'. S Source S')  (T. S Target T))"
proof -
  have A1: "TRel. strongly_operational_corresponding TRel
             S. (S'. S Source S')  (T. S Target T)"
    by blast
  moreover have A2: "S. (S'. S Source S')  (T. S Target T)
                      TRel. strongly_operational_corresponding TRel
                           weak_reduction_bisimulation TRel Target"
  proof -
    assume "S. (S'. S Source S')  (T. S Target T)"
    hence "strongly_operational_corresponding {(T1, T2). True}"
      by simp
    thus "TRel. strongly_operational_corresponding TRel
           weak_reduction_bisimulation TRel Target"
        using all_relation_is_weak_reduction_bisimulation[where Cal="Target"]
      by blast
  qed
  ultimately show "(TRel. strongly_operational_corresponding TRel
                     weak_reduction_bisimulation TRel Target)
                   = (S. (S'. S Source S')  (T. S Target T))"
    by blast
  from A1 A2 show "(TRel. strongly_operational_corresponding TRel)
                   = (S. (S'. S Source S')  (T. S Target T))"
    by blast
qed

subsection ‹(Strong) Operational Completeness vs (Strong) Simulation›

text ‹An encoding is operational complete modulo a weak simulation on target terms TRel iff there
        is a relation, like indRelRTPO, that relates at least all source terms to their literal
        translations, includes TRel, and is a weak simulation.›

lemma (in encoding) weak_reduction_simulation_impl_OCom:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and A2: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      and A3: "weak_reduction_simulation Rel (STCal Source Target)"
  shows "operational_complete (TRel*)"
proof clarify
  fix S S'
  from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
    by simp
  moreover assume "S Source* S'"
  hence "SourceTerm S (STCal Source Target)* (SourceTerm S')"
    by (simp add: STCal_steps(1))
  ultimately obtain Q' where A5: "TargetTerm (S) (STCal Source Target)* Q'"
                         and A6: "(SourceTerm S', Q')  Rel"
      using A3
    by blast
  from A5 obtain T where A7: "T ∈T Q'" and A8: "S Target* T"
    by (auto simp add: STCal_steps(2))
  from A2 A6 A7 have "(S', T)  TRel*"
    by simp
  with A8 show "T. S Target* T  (S', T)  TRel*"
    by blast
qed

lemma (in encoding) OCom_iff_indRelRTPO_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_complete (TRel*)
          weak_reduction_simulation (TRel+) Target)
         = weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume oc:  "operational_complete (TRel*)"
     and sim: "weak_reduction_simulation (TRel+) Target"
  show "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  proof clarify
    fix P Q P'
    assume "P ≲⟦⋅⟧RT<TRel> Q" and "P (STCal Source Target)* P'"
    thus "Q'. Q (STCal Source Target)* Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
    proof (induct arbitrary: P')
      case (encR S)
      assume "SourceTerm S (STCal Source Target)* P'"
      from this obtain S' where A1: "S' ∈S P'" and A2: "S Source* S'"
        by (auto simp add: STCal_steps(1))
      from oc A2 obtain T where A3: "S Target* T" and A4: "(S', T)  TRel*"
        by blast
      from A3 have "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
        by (simp add: STCal_steps(2))
      moreover have "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
      proof -
        from A4 have "S' = T  (S', T)  TRel+"
            using rtrancl_eq_or_trancl[of "S'" T TRel]
          by blast
        moreover from A1 have A5: "P' ≲⟦⋅⟧RT<TRel> TargetTerm (S')"
          by (simp add: indRelRTPO.encR)
        hence "S' = T  P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
          by simp
        moreover have "(S', T)  TRel+  P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
        proof -
          assume "(S', T)  TRel+"
          hence "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T"
          proof induct
            fix T
            assume "(S', T)  TRel"
            thus "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T"
              by (rule indRelRTPO.target)
          next
            case (step TQ TR)
            assume "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
            moreover assume "(TQ, TR)  TRel"
            hence "TargetTerm TQ ≲⟦⋅⟧RT<TRel> TargetTerm TR"
              by (rule indRelRTPO.target)
            ultimately show "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm TR"
              by (rule indRelRTPO.trans)
          qed
          with A5 show "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule indRelRTPO.trans)
        qed
        ultimately show "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
          by blast
      qed
      ultimately
      show "Q'. TargetTerm (S) (STCal Source Target)* Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (source S)
      then obtain S' where B1: "S' ∈S P'"
        by (auto simp add: STCal_steps(1))
      hence "P' ≲⟦⋅⟧RT<TRel> P'"
        by (simp add: indRelRTPO.source)
      with source show "Q'. SourceTerm S (STCal Source Target)* Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T1 (STCal Source Target)* P'"
      from this obtain T1' where C1: "T1' ∈T P'" and C2: "T1 Target* T1'"
        by (auto simp add: STCal_steps(2))
      assume "(T1, T2)  TRel"
      hence "(T1, T2)  TRel+"
        by simp
      with C2 sim obtain T2' where C3: "T2 Target* T2'"
                               and C4: "(T1', T2')  TRel+"
        by blast
      from C3 have "TargetTerm T2 (STCal Source Target)* (TargetTerm T2')"
        by (simp add: STCal_steps(2))
      moreover from C4 have "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
      proof induct
        fix T2'
        assume "(T1', T2')  TRel"
        thus "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
          by (rule indRelRTPO.target)
      next
        case (step TQ TR)
        assume "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
        moreover assume "(TQ, TR)  TRel"
        hence "TargetTerm TQ ≲⟦⋅⟧RT<TRel> TargetTerm TR"
          by (rule indRelRTPO.target)
        ultimately show "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm TR"
          by (rule indRelRTPO.trans)
      qed
      with C1 have "P' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
        by simp
      ultimately show "Q'. TargetTerm T2 (STCal Source Target)* Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (trans P Q R)
      assume "P (STCal Source Target)* P'"
         and "P'. P (STCal Source Target)* P'
               Q'. Q (STCal Source Target)* Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
      from this obtain Q' where D1: "Q (STCal Source Target)* Q'"
                            and D2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
      assume "Q'. Q (STCal Source Target)* Q'
               R'. R (STCal Source Target)* R'  Q' ≲⟦⋅⟧RT<TRel> R'"
      with D1 obtain R' where D3: "R (STCal Source Target)* R'"
                          and D4: "Q' ≲⟦⋅⟧RT<TRel> R'"
        by blast
      from D2 D4 have "P' ≲⟦⋅⟧RT<TRel> R'"
        by (rule indRelRTPO.trans)
      with D3 show "R'. R (STCal Source Target)* R'  P' ≲⟦⋅⟧RT<TRel> R'"
        by blast
    qed
  qed
next
  have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume sim: "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  ultimately have "operational_complete (TRel*)"
      using weak_reduction_simulation_impl_OCom[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by simp
  moreover from sim have "weak_reduction_simulation (TRel+) Target"
      using indRelRTPO_impl_TRel_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "operational_complete (TRel*)
                    weak_reduction_simulation (TRel+) Target"
    by simp
qed

lemma (in encoding) OCom_iff_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_complete (TRel*)
          weak_reduction_simulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_simulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "operational_complete (TRel*)"
              and "weak_reduction_simulation (TRel+) Target"
  hence "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
      using OCom_iff_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    weak_reduction_simulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_simulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    and A5: "weak_reduction_simulation Rel (STCal Source Target)"
    by blast
  from A1 A4 A5 have "operational_complete (TRel*)"
      using weak_reduction_simulation_impl_OCom[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from A2 A3 A5 have "weak_reduction_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_weak_reduction_simulation[where Rel="Rel" and
             TRel="TRel"]
    by simp
  ultimately show "operational_complete (TRel*)
                    weak_reduction_simulation (TRel+) Target"
    by simp
qed

text ‹An encoding is strong operational complete modulo a strong simulation on target terms TRel
        iff there is a relation, like indRelRTPO, that relates at least all source terms to their
        literal translations, includes TRel, and is a strong simulation.›

lemma (in encoding) strong_reduction_simulation_impl_SOCom:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and A2: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      and A3: "strong_reduction_simulation Rel (STCal Source Target)"
  shows "strongly_operational_complete (TRel*)"
proof clarify
  fix S S'
  from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
    by simp
  moreover assume "S Source S'"
  hence "SourceTerm S (STCal Source Target) (SourceTerm S')"
    by (simp add: STCal_step(1))
  ultimately obtain Q' where A5: "TargetTerm (S) (STCal Source Target) Q'"
                         and A6: "(SourceTerm S', Q')  Rel"
      using A3
    by blast
  from A5 obtain T where A7: "T ∈T Q'" and A8: "S Target T"
    by (auto simp add: STCal_step(2))
  from A2 A6 A7 have "(S', T)  TRel*"
    by simp
  with A8 show "T. S Target T  (S', T)  TRel*"
    by blast
qed

lemma (in encoding) SOCom_iff_indRelRTPO_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_complete (TRel*)
          strong_reduction_simulation (TRel+) Target)
         = strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume soc: "strongly_operational_complete (TRel*)"
     and sim: "strong_reduction_simulation (TRel+) Target"
  show "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  proof clarify
    fix P Q P'
    assume "P ≲⟦⋅⟧RT<TRel> Q" and "P (STCal Source Target) P'"
    thus "Q'. Q (STCal Source Target) Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
    proof (induct arbitrary: P')
      case (encR S)
      assume "SourceTerm S (STCal Source Target) P'"
      from this obtain S' where A1: "S' ∈S P'" and A2: "S Source S'"
        by (auto simp add: STCal_step(1))
      from soc A2 obtain T where A3: "S Target T" and A4: "(S', T)  TRel*"
        by blast
      from A3 have "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
        by (simp add: STCal_step(2))
      moreover have "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
      proof -
        from A4 have "S' = T  (S', T)  TRel+"
            using rtrancl_eq_or_trancl[of "S'" T TRel]
          by blast
        moreover from A1 have A5: "P' ≲⟦⋅⟧RT<TRel> TargetTerm (S')"
          by (simp add: indRelRTPO.encR)
        hence "S' = T  P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
          by simp
        moreover have "(S', T)  TRel+  P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
        proof -
          assume "(S', T)  TRel+"
          hence "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T"
          proof induct
            fix TQ
            assume "(S', TQ)  TRel"
            thus "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
              by (rule indRelRTPO.target)
          next
            case (step TQ TR)
            assume "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
            moreover assume "(TQ, TR)  TRel"
            hence "TargetTerm TQ ≲⟦⋅⟧RT<TRel> TargetTerm TR"
              by (rule indRelRTPO.target)
            ultimately show "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm TR"
              by (rule indRelRTPO.trans)
          qed
          with A5 show "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule indRelRTPO.trans)
        qed
        ultimately show "P' ≲⟦⋅⟧RT<TRel> TargetTerm T"
          by blast
      qed
      ultimately
      show "Q'. TargetTerm (S) (STCal Source Target) Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (source S)
      then obtain S' where B1: "S' ∈S P'"
        by (auto simp add: STCal_step(1))
      hence "P' ≲⟦⋅⟧RT<TRel> P'"
        by (simp add: indRelRTPO.source)
      with source show "Q'. SourceTerm S (STCal Source Target) Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T1 (STCal Source Target) P'"
      from this obtain T1' where C1: "T1' ∈T P'" and C2: "T1 Target T1'"
        by (auto simp add: STCal_step(2))
      assume "(T1, T2)  TRel"
      hence "(T1, T2)  TRel+"
        by simp
      with C2 sim obtain T2' where C3: "T2 Target T2'" and C4: "(T1', T2')  TRel+"
        by blast
      from C3 have "TargetTerm T2 (STCal Source Target) (TargetTerm T2')"
        by (simp add: STCal_step(2))
      moreover from C4 have "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
      proof induct
        fix T2'
        assume "(T1', T2')  TRel"
        thus "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
          by (rule indRelRTPO.target)
      next
        case (step TQ TR)
        assume "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
        moreover assume "(TQ, TR)  TRel"
        hence "TargetTerm TQ ≲⟦⋅⟧RT<TRel> TargetTerm TR"
          by (rule indRelRTPO.target)
        ultimately show "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm TR"
          by (rule indRelRTPO.trans)
      qed
      with C1 have "P' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
        by simp
      ultimately show "Q'. TargetTerm T2 (STCal Source Target) Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
    next
      case (trans P Q R)
      assume "P (STCal Source Target) P'"
         and "P'. P (STCal Source Target) P'
               Q'. Q (STCal Source Target) Q'  P' ≲⟦⋅⟧RT<TRel> Q'"
      from this obtain Q' where D1: "Q (STCal Source Target) Q'"
                            and D2: "P' ≲⟦⋅⟧RT<TRel> Q'"
        by blast
      assume "Q'. Q (STCal Source Target) Q'
               R'. R (STCal Source Target) R'  Q' ≲⟦⋅⟧RT<TRel> R'"
      with D1 obtain R' where D3: "R (STCal Source Target) R'"
                          and D4: "Q' ≲⟦⋅⟧RT<TRel> R'"
        by blast
      from D2 D4 have "P' ≲⟦⋅⟧RT<TRel> R'"
        by (rule indRelRTPO.trans)
      with D3 show "R'. R (STCal Source Target) R'  P' ≲⟦⋅⟧RT<TRel> R'"
        by blast
    qed
  qed
next
  have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume sim: "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
  ultimately have "strongly_operational_complete (TRel*)"
      using strong_reduction_simulation_impl_SOCom[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by simp
  moreover from sim have "strong_reduction_simulation (TRel+) Target"
      using indRelRTPO_impl_TRel_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "strongly_operational_complete (TRel*)
                    strong_reduction_simulation (TRel+) Target"
    by simp
qed

lemma (in encoding) SOCom_iff_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_complete (TRel*)
          strong_reduction_simulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             strong_reduction_simulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "strongly_operational_complete (TRel*)"
              and "strong_reduction_simulation (TRel+) Target"
  hence "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
      using SOCom_iff_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    strong_reduction_simulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           strong_reduction_simulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    and A5: "strong_reduction_simulation Rel (STCal Source Target)"
    by blast
  from A1 A4 A5 have "strongly_operational_complete (TRel*)"
      using strong_reduction_simulation_impl_SOCom[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from A2 A3 A5 have "strong_reduction_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_strong_reduction_simulation[where Rel="Rel" and
             TRel="TRel"]
    by simp
  ultimately show "strongly_operational_complete (TRel*)
                    strong_reduction_simulation (TRel+) Target"
    by simp
qed

lemma (in encoding) target_relation_from_source_target_relation:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes stre: "S T. (SourceTerm S, TargetTerm T)  Rel
                  (TargetTerm (S), TargetTerm T)  Rel="
  shows "TRel. (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)"
proof -
  define TRel where "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
  from TRel_def have "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by simp
  moreover from TRel_def
  have "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by blast
  moreover from stre TRel_def
  have "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    by blast
  ultimately show ?thesis
    by blast
qed

lemma (in encoding) SOCom_modulo_TRel_iff_strong_reduction_simulation:
  shows "(TRel. strongly_operational_complete (TRel*)
          strong_reduction_simulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
            (S T. (SourceTerm S, TargetTerm T)  Rel  (TargetTerm (S), TargetTerm T)  Rel=)
            strong_reduction_simulation Rel (STCal Source Target))"
proof (rule iffI)
  assume "TRel. strongly_operational_complete (TRel*)
           strong_reduction_simulation (TRel+) Target"
  from this obtain TRel where "strongly_operational_complete (TRel*)"
                          and "strong_reduction_simulation (TRel+) Target"
    by blast
  hence "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
      using SOCom_iff_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  moreover have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T
                  (TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
      using indRelRTPO_relates_source_target[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (S T. (SourceTerm S, TargetTerm T)  Rel
                       (TargetTerm (S), TargetTerm T)  Rel=)
                    strong_reduction_simulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (TargetTerm (S), TargetTerm T)  Rel=)
           strong_reduction_simulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "(S T. (SourceTerm S, TargetTerm T)  Rel
                                   (TargetTerm (S), TargetTerm T)  Rel=)"
                         and A3: "strong_reduction_simulation Rel (STCal Source Target)"
    by blast
  from A2 obtain TRel where "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using target_relation_from_source_target_relation[where Rel="Rel"]
    by blast
  with A1 A3 have "strongly_operational_complete (TRel*)
                    strong_reduction_simulation (TRel+) Target"
      using SOCom_iff_strong_reduction_simulation[where TRel="TRel"]
    by blast
  thus "TRel. strongly_operational_complete (TRel*)
         strong_reduction_simulation (TRel+) Target"
    by blast
qed

subsection ‹Weak Operational Soundness vs Contrasimulation›

text ‹If the inverse of a relation that includes TRel and relates source terms and their literal
        translations is a contrasimulation, then the encoding is weakly operational sound.›

lemma (in encoding) weak_reduction_contrasimulation_impl_WOSou:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and A2: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      and A3: "weak_reduction_contrasimulation (Rel¯) (STCal Source Target)"
  shows "weakly_operational_sound (TRel*)"
proof clarify
  fix S T
  from A1 have "(TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover assume "S Target* T"
  hence "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
    by (simp add: STCal_steps(2))
  ultimately obtain Q' where A5: "SourceTerm S (STCal Source Target)* Q'"
                         and A6: "(Q', TargetTerm T)  Rel¯"
      using A3
    by blast
  from A5 obtain S' where A7: "S' ∈S Q'" and A8: "S Source* S'"
    by (auto simp add: STCal_steps(1))
  have "Q' (STCal Source Target)* Q'"
    by (simp add: steps_refl)
  with A6 A3 obtain P'' where A9:  "TargetTerm T (STCal Source Target)* P''"
                          and A10: "(P'', Q')  Rel¯"
    by blast
  from A9 obtain T' where A11: "T' ∈T P''" and A12: "T Target* T'"
    by (auto simp add: STCal_steps(2))
  from A10 have "(Q', P'')  Rel"
    by induct
  with A2 A7 A11 have "(S', T')  TRel*"
    by simp
  with A8 A12 show "S' T'. S Source* S'  T Target* T'  (S', T')  TRel*"
    by blast
qed

subsection ‹(Strong) Operational Soundness vs (Strong) Simulation›

text ‹An encoding is operational sound modulo a relation TRel whose inverse is a weak reduction
        simulation on target terms iff there is a relation, like indRelRTPO, that relates at least
        all source terms to their literal translations, includes TRel, and whose inverse is a weak
        simulation.›

lemma (in encoding) weak_reduction_simulation_impl_OSou:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and A2: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      and A3: "weak_reduction_simulation (Rel¯) (STCal Source Target)"
  shows "operational_sound (TRel*)"
proof clarify
  fix S T
  from A1 have "(TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover assume "S Target* T"
  hence "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
    by (simp add: STCal_steps(2))
  ultimately obtain Q' where A5: "SourceTerm S (STCal Source Target)* Q'"
                         and A6: "(TargetTerm T, Q')  Rel¯"
      using A3
    by blast
  from A5 obtain S' where A7: "S' ∈S Q'" and A8: "S Source* S'"
    by (auto simp add: STCal_steps(1))
  from A6 have "(Q', TargetTerm T)  Rel"
    by induct
  with A2 A7 have "(S', T)  TRel*"
    by simp
  with A8 show "S'. S Source* S'  (S', T)  TRel*"
    by blast
qed

lemma (in encoding) OSou_iff_inverse_of_indRelRTPO_is_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_sound (TRel*)
          weak_reduction_simulation ((TRel+)¯) Target)
         = weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume os:  "operational_sound (TRel*)"
     and sim: "weak_reduction_simulation ((TRel+)¯) Target"
  show "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  proof clarify
    fix P Q P'
    assume "Q ≲⟦⋅⟧RT<TRel> P" and "P (STCal Source Target)* P'"
    thus "Q'. Q (STCal Source Target)* Q'  (P', Q')  (indRelRTPO TRel)¯"
    proof (induct arbitrary: P')
      case (encR S)
      assume "TargetTerm (S) (STCal Source Target)* P'"
      from this obtain T where A1: "T ∈T P'" and A2: "S Target* T"
        by (auto simp add: STCal_steps(2))
      from os A2 obtain S' where A3: "S Source* S'" and A4: "(S', T)  TRel*"
        by blast
      from A3 have "SourceTerm S (STCal Source Target)* (SourceTerm S')"
        by (simp add: STCal_steps(1))
      moreover have "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
      proof -
        from A4 have "S' = T  (S', T)  TRel+"
            using rtrancl_eq_or_trancl[of "S'" T TRel]
          by blast
        moreover have A5: "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm (S')"
          by (simp add: indRelRTPO.encR)
        with A1 have "S' = T  SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
          by simp
        moreover have "(S', T)  TRel+  SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
        proof -
          assume "(S', T)  TRel+"
          hence "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule transitive_closure_of_TRel_to_indRelRTPO)
          with A5 have "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule indRelRTPO.trans)
          with A1 show "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
            by simp
        qed
        ultimately show "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
          by blast
      qed
      hence "(P', SourceTerm S')  (indRelRTPO TRel)¯"
        by simp
      ultimately
      show "Q'. SourceTerm S (STCal Source Target)* Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (source S)
      then obtain S' where B1: "S' ∈S P'"
        by (auto simp add: STCal_steps(1))
      hence "(P', P')  (indRelRTPO TRel)¯"
        by (simp add: indRelRTPO.source)
      with source
      show "Q'. SourceTerm S (STCal Source Target)* Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T2 (STCal Source Target)* P'"
      from this obtain T2' where C1: "T2' ∈T P'" and C2: "T2 Target* T2'"
        by (auto simp add: STCal_steps(2))
      assume "(T1, T2)  TRel"
      hence "(T2, T1)  (TRel+)¯"
        by simp
      with C2 sim obtain T1' where C3: "T1 Target* T1'" and C4: "(T2', T1')  (TRel+)¯"
        by blast
      from C3 have "TargetTerm T1 (STCal Source Target)* (TargetTerm T1')"
        by (simp add: STCal_steps(2))
      moreover from C4 have "(T1', T2')  TRel+"
        by induct
      hence "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
        by (rule transitive_closure_of_TRel_to_indRelRTPO)
      with C1 have "(P', TargetTerm T1')  (indRelRTPO TRel)¯"
        by simp
      ultimately
      show "Q'. TargetTerm T1 (STCal Source Target)* Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (trans P Q R R')
      assume "R (STCal Source Target)* R'"
         and "R'. R (STCal Source Target)* R'
               Q'. Q (STCal Source Target)* Q'  (R', Q')  (indRelRTPO TRel)¯"
      from this obtain Q' where D1: "Q (STCal Source Target)* Q'"
                            and D2: "(R', Q')  (indRelRTPO TRel)¯"
        by blast
      assume "Q'. Q (STCal Source Target)* Q'
               P'. P (STCal Source Target)* P'  (Q', P')  (indRelRTPO TRel)¯"
      with D1 obtain P' where D3: "P (STCal Source Target)* P'"
                          and D4: "(Q', P')  (indRelRTPO TRel)¯"
        by blast
      from D4 D2 have "(R', P')  (indRelRTPO TRel)¯"
        by (simp add: indRelRTPO.trans[where P="P'" and Q="Q'" and R="R'"])
      with D3 show "P'. P (STCal Source Target)* P'  (R', P')  (indRelRTPO TRel)¯"
        by blast
    qed
  qed
next
  have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover
  assume sim: "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  ultimately have "operational_sound (TRel*)"
      using weak_reduction_simulation_impl_OSou[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by simp
  moreover from sim have "weak_reduction_simulation ((TRel+)¯) Target"
      using indRelRTPO_impl_TRel_is_weak_reduction_simulation_rev[where TRel="TRel"]
    by simp
  ultimately show "operational_sound (TRel*)  weak_reduction_simulation ((TRel+)¯) Target"
    by simp
qed

lemma (in encoding) OSou_iff_weak_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_sound (TRel*)
          weak_reduction_simulation ((TRel+)¯) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_simulation (Rel¯) (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "operational_sound (TRel*)"
              and "weak_reduction_simulation ((TRel+)¯) Target"
  hence "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using OSou_iff_inverse_of_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    weak_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_simulation (Rel¯) (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    and A5: "weak_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
  from A1 A4 A5 have "operational_sound (TRel*)"
      using weak_reduction_simulation_impl_OSou[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from A2 A3 A5 have "weak_reduction_simulation ((TRel+)¯) Target"
      using rel_with_target_impl_transC_TRel_is_weak_reduction_simulation_rev[where Rel="Rel" and
             TRel="TRel"]
    by simp
  ultimately show "operational_sound (TRel*)  weak_reduction_simulation ((TRel+)¯) Target"
    by simp
qed

text ‹An encoding is strongly operational sound modulo a relation TRel whose inverse is a strong
        reduction simulation on target terms iff there is a relation, like indRelRTPO, that relates
        at least all source terms to their literal translations, includes TRel, and whose inverse
        is a strong simulation.›

lemma (in encoding) strong_reduction_simulation_impl_SOSou:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and A2: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      and A3: "strong_reduction_simulation (Rel¯) (STCal Source Target)"
  shows "strongly_operational_sound (TRel*)"
proof clarify
  fix S T
  from A1 have "(TargetTerm (S), SourceTerm S)  Rel¯"
    by simp
  moreover assume "S Target T"
  hence "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
    by (simp add: STCal_step(2))
  ultimately obtain Q' where A5: "SourceTerm S (STCal Source Target) Q'"
                         and A6: "(TargetTerm T, Q')  Rel¯"
      using A3
    by blast
  from A5 obtain S' where A7: "S' ∈S Q'" and A8: "S Source S'"
    by (auto simp add: STCal_step(1))
  from A6 have "(Q', TargetTerm T)  Rel"
    by induct
  with A2 A7 have "(S', T)  TRel*"
    by simp
  with A8 show "S'. S Source S'  (S', T)  TRel*"
    by blast
qed

lemma (in encoding) SOSou_iff_inverse_of_indRelRTPO_is_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_sound (TRel*)
          strong_reduction_simulation ((TRel+)¯) Target)
         = strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume os:  "strongly_operational_sound (TRel*)"
     and sim: "strong_reduction_simulation ((TRel+)¯) Target"
  show "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  proof clarify
    fix P Q P'
    assume "Q ≲⟦⋅⟧RT<TRel> P"
    moreover assume "P (STCal Source Target) P'"
    ultimately
    show "Q'. Q (STCal Source Target) Q'  (P', Q')  (indRelRTPO TRel)¯"
    proof (induct arbitrary: P')
      case (encR S)
      assume "TargetTerm (S) (STCal Source Target) P'"
      from this obtain T where A1: "T ∈T P'" and A2: "S Target T"
        by (auto simp add: STCal_step(2))
      from os A2 obtain S' where A3: "S Source S'" and A4: "(S', T)  TRel*"
        by blast
      from A3 have "SourceTerm S (STCal Source Target) (SourceTerm S')"
        by (simp add: STCal_step(1))
      moreover have "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
      proof -
        from A4 have "S' = T  (S', T)  TRel+"
            using rtrancl_eq_or_trancl[of "S'" T TRel]
          by blast
        moreover have A5: "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm (S')"
          by (simp add: indRelRTPO.encR)
        with A1 have "S' = T  SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
          by simp
        moreover have "(S', T)  TRel+  SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
        proof -
          assume "(S', T)  TRel+"
          hence "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule transitive_closure_of_TRel_to_indRelRTPO)
          with A5 have "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T"
            by (rule indRelRTPO.trans)
          with A1 show "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
            by simp
        qed
        ultimately show "SourceTerm S' ≲⟦⋅⟧RT<TRel> P'"
          by blast
      qed
      hence "(P', SourceTerm S')  (indRelRTPO TRel)¯"
        by simp
      ultimately
      show "Q'. SourceTerm S (STCal Source Target) Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (source S)
      then obtain S' where B1: "S' ∈S P'"
        by (auto simp add: STCal_step(1))
      hence "(P', P')  (indRelRTPO TRel)¯"
        by (simp add: indRelRTPO.source)
      with source
      show "Q'. SourceTerm S (STCal Source Target) Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T2 (STCal Source Target) P'"
      from this obtain T2' where C1: "T2' ∈T P'" and C2: "T2 Target T2'"
        by (auto simp add: STCal_step(2))
      assume "(T1, T2)  TRel"
      hence "(T2, T1)  (TRel+)¯"
        by simp
      with C2 sim obtain T1' where C3: "T1 Target T1'" and C4: "(T2', T1')  (TRel+)¯"
        by blast
      from C3 have "TargetTerm T1 (STCal Source Target) (TargetTerm T1')"
        by (simp add: STCal_step(2))
      moreover from C4 have "(T1', T2')  TRel+"
        by induct
      hence "TargetTerm T1' ≲⟦⋅⟧RT<TRel> TargetTerm T2'"
        by (rule transitive_closure_of_TRel_to_indRelRTPO)
      with C1 have "(P', TargetTerm T1')  (indRelRTPO TRel)¯"
        by simp
      ultimately
      show "Q'. TargetTerm T1 (STCal Source Target) Q'  (P', Q')  (indRelRTPO TRel)¯"
        by blast
    next
      case (trans P Q R R')
      assume "R (STCal Source Target) R'"
         and "R'. R (STCal Source Target) R'
               Q'. Q (STCal Source Target) Q'  (R', Q')  (indRelRTPO TRel)¯"
      from this obtain Q' where D1: "Q (STCal Source Target) Q'"
                            and D2: "(R', Q')  (indRelRTPO TRel)¯"
        by blast
      assume "Q'. Q (STCal Source Target) Q'
               P'. P (STCal Source Target) P'  (Q', P')  (indRelRTPO TRel)¯"
      with D1 obtain P' where D3: "P (STCal Source Target) P'"
                          and D4: "(Q', P')  (indRelRTPO TRel)¯"
        by blast
      from D4 D2 have "(R', P')  (indRelRTPO TRel)¯"
        by (simp add: indRelRTPO.trans[where P="P'" and Q="Q'" and R="R'"])
      with D3 show "P'. P (STCal Source Target) P'  (R', P')  (indRelRTPO TRel)¯"
        by blast
    qed
  qed
next
  have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover
  assume sim: "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
  ultimately have "strongly_operational_sound (TRel*)"
      using strong_reduction_simulation_impl_SOSou[where Rel="indRelRTPO TRel" and TRel="TRel"]
    by simp
  moreover from sim have "strong_reduction_simulation ((TRel+)¯) Target"
      using indRelRTPO_impl_TRel_is_strong_reduction_simulation_rev[where TRel="TRel"]
    by simp
  ultimately
  show "strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target"
    by simp
qed

lemma (in encoding) SOSou_iff_strong_reduction_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             strong_reduction_simulation (Rel¯) (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "strongly_operational_sound (TRel*)"
              and "strong_reduction_simulation ((TRel+)¯) Target"
  hence "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using SOSou_iff_inverse_of_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    strong_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           strong_reduction_simulation (Rel¯) (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    and A5: "strong_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
  from A1 A4 A5 have "strongly_operational_sound (TRel*)"
      using strong_reduction_simulation_impl_SOSou[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from A2 A3 A5 have "strong_reduction_simulation ((TRel+)¯) Target"
      using rel_with_target_impl_transC_TRel_is_strong_reduction_simulation_rev[where Rel="Rel" and
             TRel="TRel"]
    by simp
  ultimately
  show "strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target"
    by simp
qed

lemma (in encoding) SOSou_modulo_TRel_iff_strong_reduction_simulation:
  shows "(TRel. strongly_operational_sound (TRel*)
          strong_reduction_simulation ((TRel+)¯) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
            (S T. (SourceTerm S, TargetTerm T)  Rel  (TargetTerm (S), TargetTerm T)  Rel=)
            strong_reduction_simulation (Rel¯) (STCal Source Target))"
proof (rule iffI)
  assume "TRel. strongly_operational_sound (TRel*)
           strong_reduction_simulation ((TRel+)¯) Target"
  from this obtain TRel where "strongly_operational_sound (TRel*)"
                          and "strong_reduction_simulation ((TRel+)¯) Target"
    by blast
  hence "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using SOSou_iff_inverse_of_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  moreover have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. (SourceTerm S, TargetTerm T)  indRelRTPO TRel
                  (TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
      using indRelRTPO_relates_source_target[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (S T. (SourceTerm S, TargetTerm T)  Rel
                       (TargetTerm (S), TargetTerm T)  Rel=)
                    strong_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (S T. (SourceTerm S, TargetTerm T)  Rel
              (TargetTerm (S), TargetTerm T)  Rel=)
           strong_reduction_simulation (Rel¯) (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and A2: "(S T. (SourceTerm S, TargetTerm T)  Rel
             (TargetTerm (S), TargetTerm T)  Rel=)"
   and A3: "strong_reduction_simulation (Rel¯) (STCal Source Target)"
    by blast
  from A2 obtain TRel where "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using target_relation_from_source_target_relation[where Rel="Rel"]
    by blast
  with A1 A3
  have "strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target"
      using SOSou_iff_strong_reduction_simulation[where TRel="TRel"]
    by blast
  thus "TRel. strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target"
    by blast
qed

subsection ‹Weak Operational Correspondence vs Correspondence Similarity›

text ‹If there exists a relation that relates at least all source terms and their literal
        translations, includes TRel, and is a correspondence simulation then the encoding is weakly
        operational corresponding w.r.t. TRel.›

lemma (in encoding) weak_reduction_correspondence_simulation_impl_WOC:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes enc:  "S. (SourceTerm S, TargetTerm (S))  Rel"
      and tRel: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)"
      and cs:   "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
  shows "weakly_operational_corresponding (TRel*)"
proof
  from enc tRel cs show "operational_complete (TRel*)"
      using weak_reduction_simulation_impl_OCom[where TRel="TRel"]
    by simp
next
  show "weakly_operational_sound (TRel*)"
  proof clarify
    fix S T
    from enc have "(SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover assume "S Target* T"
    hence "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
      by (simp add: STCal_steps(2))
    ultimately obtain P' Q' where A1: "SourceTerm S (STCal Source Target)* P'"
     and A2: "TargetTerm T (STCal Source Target)* Q'" and A3: "(P', Q')  Rel"
        using cs
      by blast
    from A1 obtain S' where A4: "S' ∈S P'" and A5: "S Source* S'"
      by (auto simp add: STCal_steps(1))
    from A2 obtain T' where A6: "T' ∈T Q'" and A7: "T Target* T'"
      by (auto simp: STCal_steps(2))
    from tRel A3 A4 A6 have "(S', T')  TRel*"
      by simp
    with A5 A7 show "S' T'. S Source* S'  T Target* T'  (S', T')  TRel*"
      by blast
  qed
qed

text ‹An encoding is weakly operational corresponding w.r.t. a correspondence simulation on
        target terms TRel iff there exists a relation, like indRelRTPO, that relates at least all
        source terms and their literal translations, includes TRel, and is a correspondence
        simulation.›

lemma (in encoding) WOC_iff_indRelRTPO_is_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding (TRel*)
          weak_reduction_correspondence_simulation (TRel+) Target)
         = weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume woc: "weakly_operational_corresponding (TRel*)"
     and csi: "weak_reduction_correspondence_simulation (TRel+) Target"
  show "weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
  proof
    from woc csi show sim: "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
        using OCom_iff_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
      by simp
    show "P Q Q'. P ≲⟦⋅⟧RT<TRel> Q  Q (STCal Source Target)* Q'
           (P'' Q''. P (STCal Source Target)* P''  Q' (STCal Source Target)* Q''
           P'' ≲⟦⋅⟧RT<TRel> Q'')"
    proof clarify
      fix P Q Q'
      assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q (STCal Source Target)* Q'"
      thus "P'' Q''. P (STCal Source Target)* P''  Q' (STCal Source Target)* Q''
             P'' ≲⟦⋅⟧RT<TRel> Q''"
      proof (induct arbitrary: Q')
        case (encR S)
        assume "TargetTerm (S) (STCal Source Target)* Q'"
        from this obtain T where A1: "T ∈T Q'" and A2: "S Target* T"
          by (auto simp add: STCal_steps(2))
        from A2 woc obtain S' T' where A3: "S Source* S'" and A4: "T Target* T'"
                                   and A5: "(S', T')  TRel*"
          by blast
        from A3 have "SourceTerm S (STCal Source Target)* (SourceTerm S')"
          by (simp add: STCal_steps(1))
        moreover from A4 have "TargetTerm T (STCal Source Target)* (TargetTerm T')"
          by (simp add: STCal_steps(2))
        moreover have "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T'"
        proof -
          have A6: "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm (S')"
            by (rule indRelRTPO.encR)
          from A5 have "S' = T'  (S', T')  TRel+"
              using rtrancl_eq_or_trancl[of "S'" T' TRel]
            by blast
          moreover from A6 have "S' = T'  SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T'"
            by simp
          moreover have "(S', T')  TRel+  SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T'"
          proof -
            assume "(S', T')  TRel+"
            hence "TargetTerm (S') ≲⟦⋅⟧RT<TRel> TargetTerm T'"
              by (simp add: transitive_closure_of_TRel_to_indRelRTPO[where TRel="TRel"])
            with A6 show "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T'"
              by (rule indRelRTPO.trans)
          qed
          ultimately show "SourceTerm S' ≲⟦⋅⟧RT<TRel> TargetTerm T'"
            by blast
        qed
        ultimately show "P'' Q''. SourceTerm S (STCal Source Target)* P''
                          Q' (STCal Source Target)* Q''  P'' ≲⟦⋅⟧RT<TRel> Q''"
            using A1
          by blast
      next
        case (source S)
        assume B1: "SourceTerm S (STCal Source Target)* Q'"
        moreover have "Q' (STCal Source Target)* Q'"
          by (rule steps_refl)
        moreover from B1 obtain S' where "S' ∈S Q'"
          by (auto simp add: STCal_steps(1))
        hence "Q' ≲⟦⋅⟧RT<TRel> Q'"
          by (simp add: indRelRTPO.source)
        ultimately show "P'' Q''. SourceTerm S (STCal Source Target)* P''
                          Q' (STCal Source Target)* Q''  P'' ≲⟦⋅⟧RT<TRel> Q''"
          by blast
      next
        case (target T1 T2)
        assume "TargetTerm T2 (STCal Source Target)* Q'"
        from this obtain T2' where C1: "T2' ∈T Q'" and C2: "T2 Target* T2'"
          by (auto simp add: STCal_steps(2))
        assume "(T1, T2)  TRel"
        hence "(T1, T2)  TRel+"
          by simp
        with C2 csi obtain T1' T2'' where C3: "T1 Target* T1'" and C4: "T2' Target* T2''"
                                      and C5: "(T1', T2'')  TRel+"
          by blast
        from C3 have "TargetTerm T1 (STCal Source Target)* (TargetTerm T1')"
          by (simp add: STCal_steps(2))
        moreover from C1 C4 have "Q' (STCal Source Target)* (TargetTerm T2'')"
          by (simp add: STCal_steps(2))
        moreover from C5 have "TargetTerm T1' ≲⟦⋅⟧RT<TRel> (TargetTerm T2'')"
          by (simp add: transitive_closure_of_TRel_to_indRelRTPO)
        ultimately show "P'' Q''. TargetTerm T1 (STCal Source Target)* P''
                          Q' (STCal Source Target)* Q''  P'' ≲⟦⋅⟧RT<TRel> Q''"
          by blast
      next
        case (trans P Q R R')
        assume "R (STCal Source Target)* R'"
           and "R'. R (STCal Source Target)* R'  Q'' R''. Q (STCal Source Target)* Q''
                 R' (STCal Source Target)* R''  Q'' ≲⟦⋅⟧RT<TRel> R''"
           and "Q'. Q (STCal Source Target)* Q'  P'' Q''. P (STCal Source Target)* P''
                 Q' (STCal Source Target)* Q''  P'' ≲⟦⋅⟧RT<TRel> Q''"
        moreover have "trans (indRelRTPO TRel)"
            using indRelRTPO.trans
            unfolding trans_def
          by blast
        ultimately show ?case
            using sim reduction_correspondence_simulation_condition_trans[where P="P" and
                   Rel="indRelRTPO TRel" and Cal="STCal Source Target" and Q="Q" and R="R"]
          by blast
      qed
    qed
  qed
next
  assume csi: "weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
  show "weakly_operational_corresponding (TRel*)
         weak_reduction_correspondence_simulation (TRel+) Target"
  proof
    have " S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
      by (simp add: indRelRTPO.encR)
    moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
        using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
      by simp
    ultimately show "weakly_operational_corresponding (TRel*)"
        using weak_reduction_correspondence_simulation_impl_WOC[where Rel="indRelRTPO TRel" and
               TRel="TRel"] csi
      by simp
  next
    from csi show "weak_reduction_correspondence_simulation (TRel+) Target"
        using indRelRTPO_impl_TRel_is_weak_reduction_correspondence_simulation[where TRel="TRel"]
      by simp
  qed
qed

lemma (in encoding) WOC_iff_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding (TRel*)
          weak_reduction_correspondence_simulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_correspondence_simulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "weakly_operational_corresponding (TRel*)"
              and "weak_reduction_correspondence_simulation (TRel+) Target"
  hence "weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
      using WOC_iff_indRelRTPO_is_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_correspondence_simulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
   and A5: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
  from A1 A4 A5 have "weakly_operational_corresponding (TRel*)"
      using weak_reduction_correspondence_simulation_impl_WOC[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from A2 A3 A5 have "weak_reduction_correspondence_simulation (TRel+) Target"
      using rel_with_target_impl_transC_TRel_is_weak_reduction_correspondence_simulation
    by simp
  ultimately show "weakly_operational_corresponding (TRel*)
                    weak_reduction_correspondence_simulation (TRel+) Target"
    by simp
qed

lemma rel_includes_TRel_modulo_preorder:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and TRel :: "('procT × 'procT) set"
  assumes transT: "trans TRel"
  shows "((T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+))
         = (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})"
proof (rule iffI, erule conjE)
  assume "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
     and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
  with transT show "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using trancl_id[of TRel]
    by blast
next
  assume A: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
  hence "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by simp
  moreover from transT A
  have "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
      using trancl_id[of TRel]
    by blast
  ultimately show "(T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)"
    by simp
qed

lemma (in encoding) WOC_wrt_preorder_iff_reduction_correspondence_simulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding TRel  preorder TRel
          weak_reduction_correspondence_simulation TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             preorder Rel
             weak_reduction_correspondence_simulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE, erule conjE, erule conjE)
  assume A1: "operational_complete TRel" and A2: "weakly_operational_sound TRel"
     and A3:"preorder TRel" and A4: "weak_reduction_correspondence_simulation TRel Target"
  from A3 have A5: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  with A3 have "TRel* = TRel"
      using trancl_id[of TRel] reflcl_trancl[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  with A1 A2 have "weakly_operational_corresponding (TRel*)"
    by simp
  moreover from A4 A5 have "weak_reduction_correspondence_simulation (TRel+) Target"
    by simp
  ultimately
  have "weak_reduction_correspondence_simulation (indRelRTPO TRel) (STCal Source Target)"
      using WOC_iff_indRelRTPO_is_reduction_correspondence_simulation[where TRel="TRel"]
    by blast
  moreover have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover
  have "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  indRelRTPO TRel}"
  proof auto
    fix TP TQ
    assume "(TP, TQ)  TRel"
    thus "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
      by (rule indRelRTPO.target)
  next
    fix TP TQ
    assume "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
    with A3 show "(TP, TQ)  TRel"
        using indRelRTPO_to_TRel(4)[where TRel="TRel"] trancl_id[of TRel]
        unfolding preorder_on_def
      by blast
  qed
  moreover from A3
  have "S T. (SourceTerm S, TargetTerm T)  indRelRTPO TRel  (S, T)  TRel+"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] reflcl_trancl[of TRel]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      unfolding preorder_on_def refl_on_def
    by blast
  with A3 have "S T. (SourceTerm S, TargetTerm T)  indRelRTPO TRel  (S, T)  TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  moreover from A3 have "refl (indRelRTPO TRel)"
      using indRelRTPO_refl[of TRel]
      unfolding preorder_on_def
    by simp
  moreover have "trans (indRelRTPO TRel)"
      using indRelRTPO.trans
      unfolding trans_def
    by blast
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
                    preorder Rel
                    weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      unfolding preorder_on_def
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           preorder Rel
           weak_reduction_correspondence_simulation Rel (STCal Source Target)"
  from this obtain Rel where B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel" and B4: "preorder Rel"
   and B5: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
  from B2 B4 have B6: "refl TRel"
      unfolding preorder_on_def refl_on_def
    by blast
  from B2 B4 have B7: "trans TRel"
      unfolding trans_def preorder_on_def
    by blast
  hence B8: "TRel+ = TRel"
      using trancl_id[of TRel]
    by simp
  with B6 have "TRel* = TRel"
      using reflcl_trancl[of TRel]
      unfolding refl_on_def
    by blast
  with B1 B3 B5 have "weakly_operational_corresponding TRel"
      using weak_reduction_correspondence_simulation_impl_WOC[where Rel="Rel" and TRel="TRel"]
    by simp
  moreover from B6 B7 have "preorder TRel"
      unfolding preorder_on_def
    by blast
  moreover from B2 B5 B7 B8 have "weak_reduction_correspondence_simulation TRel Target"
      using rel_includes_TRel_modulo_preorder[where Rel="Rel" and TRel="TRel"]
            rel_with_target_impl_transC_TRel_is_weak_reduction_correspondence_simulation[where
               Rel="Rel" and TRel="TRel"]
      by fast
  ultimately show "weakly_operational_corresponding TRel  preorder TRel
                    weak_reduction_correspondence_simulation TRel Target"
    by blast
qed

subsection ‹(Strong) Operational Correspondence vs (Strong) Bisimilarity›

text ‹An encoding is operational corresponding w.r.t a weak bisimulation on target terms TRel iff
        there exists a relation, like indRelRTPO, that relates at least all source terms and their
        literal translations, includes TRel, and is a weak bisimulation. Thus this variant of
        operational correspondence ensures that source terms and their translations are weak
        bisimilar.›

lemma (in encoding) OC_iff_indRelRTPO_is_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_corresponding (TRel*)
          weak_reduction_bisimulation (TRel+) Target)
         = weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume ocorr: "operational_corresponding (TRel*)"
     and bisim: "weak_reduction_bisimulation (TRel+) Target"
  hence "weak_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
      using OCom_iff_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  moreover from bisim have "weak_reduction_simulation ((TRel+)¯) Target"
      using weak_reduction_bisimulations_impl_inverse_is_simulation[where Rel="TRel+"]
    by simp
  with ocorr have "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using OSou_iff_inverse_of_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using weak_reduction_simulations_impl_bisimulation[where Rel="indRelRTPO TRel"]
    by simp
next
  assume bisim: "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
  hence "operational_complete (TRel*)  weak_reduction_simulation (TRel+) Target"
      using OCom_iff_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  moreover from bisim
  have "weak_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using weak_reduction_bisimulations_impl_inverse_is_simulation[where Rel="indRelRTPO TRel"]
    by simp
  hence "operational_sound (TRel*)  weak_reduction_simulation ((TRel+)¯) Target"
      using OSou_iff_inverse_of_indRelRTPO_is_weak_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "operational_corresponding (TRel*)  weak_reduction_bisimulation (TRel+) Target"
      using weak_reduction_simulations_impl_bisimulation[where Rel="TRel+"]
    by simp
qed

lemma (in encoding) OC_iff_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_corresponding (TRel*)  weak_reduction_bisimulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "operational_corresponding (TRel*)"
              and "weak_reduction_bisimulation (TRel+) Target"
  hence "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
   and A5: "weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_complete (TRel*)
          weak_reduction_simulation (TRel+) Target"
      using OCom_iff_weak_reduction_simulation[where TRel="TRel"]
    by blast
  moreover from A5 have "weak_reduction_simulation (Rel¯) (STCal Source Target)"
      using weak_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel"]
    by simp
  with A1 A2 A3 A4 have "operational_sound (TRel*)
                          weak_reduction_simulation ((TRel+)¯) Target"
      using OSou_iff_weak_reduction_simulation[where TRel="TRel"]
    by blast
  ultimately show "operational_corresponding (TRel*)
                    weak_reduction_bisimulation (TRel+) Target"
      using weak_reduction_simulations_impl_bisimulation[where Rel="TRel+"]
    by simp
qed

lemma (in encoding) OC_wrt_preorder_iff_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(operational_corresponding TRel  preorder TRel
          weak_reduction_bisimulation TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             preorder Rel
             weak_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE, erule conjE, erule conjE)
  assume A1: "operational_complete TRel" and A2: "operational_sound TRel"
     and A3:"preorder TRel" and A4: "weak_reduction_bisimulation TRel Target"
  from A3 have A5: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  with A3 have "TRel* = TRel"
      using reflcl_trancl[of TRel]
      unfolding preorder_on_def refl_on_def
    by blast
  with A1 A2 have "operational_corresponding (TRel*)"
    by simp
  moreover from A4 A5 have "weak_reduction_bisimulation (TRel+) Target"
    by simp
  ultimately
  have "weak_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by blast
  moreover have "S. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm (S)"
    by (simp add: indRelRTPO.encR)
  moreover
  have "TRel = {(T1, T2). TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2}"
  proof auto
    fix TP TQ
    assume "(TP, TQ)  TRel"
    thus "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
      by (rule indRelRTPO.target)
  next
    fix TP TQ
    assume "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
    with A3 show "(TP, TQ)  TRel"
        using indRelRTPO_to_TRel(4)[where TRel="TRel"] trancl_id[of TRel]
        unfolding preorder_on_def
      by blast
  qed
  moreover from A3
  have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel+"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] reflcl_trancl[of TRel]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      unfolding preorder_on_def refl_on_def
    by auto
  with A3 have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  moreover from A3 have "refl (indRelRTPO TRel)"
      unfolding preorder_on_def
    by (simp add: indRelRTPO_refl)
  moreover have "trans (indRelRTPO TRel)"
      using indRelRTPO.trans
      unfolding trans_def
    by blast
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
                    preorder Rel
                    weak_reduction_bisimulation Rel (STCal Source Target)"
      unfolding preorder_on_def
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           preorder Rel
           weak_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel" and B4: "preorder Rel"
   and B5: "weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  from B2 B4 have B6: "refl TRel"
      unfolding preorder_on_def refl_on_def
    by blast
  from B2 B4 have B7: "trans TRel"
      unfolding trans_def preorder_on_def
    by blast
  hence B8: "TRel+ = TRel"
      using trancl_id[of TRel]
    by simp
  with B6 have B9: "TRel* = TRel"
      using reflcl_trancl[of TRel]
      unfolding refl_on_def
    by blast
  with B3 have "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    by simp
  moreover from B2 B8 have "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by auto
  ultimately have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
    weak_reduction_bisimulation Rel (STCal Source Target)"
      using B1 B5
    by blast
  hence "operational_corresponding (TRel*)
          weak_reduction_bisimulation (TRel+) Target"
      using OC_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  with B8 B9 have "operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
    by simp
  moreover from B6 B7 have "preorder TRel"
      unfolding preorder_on_def
    by blast
  ultimately show "operational_corresponding TRel  preorder TRel
                    weak_reduction_bisimulation TRel Target"
    by blast
qed

lemma (in encoding) OC_wrt_equivalence_iff_indRelTEQ_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes eqT: "equivalence TRel"
  shows "(operational_corresponding TRel  weak_reduction_bisimulation TRel Target) 
         weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume oc: "operational_corresponding TRel" and bisimT: "weak_reduction_bisimulation TRel Target"
  show "weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  proof auto
    fix P Q P'
    assume "P ∼⟦⋅⟧T<TRel> Q" and "P (STCal Source Target)* P'"
    thus "Q'. Q (STCal Source Target)* Q'  P' ∼⟦⋅⟧T<TRel> Q'"
    proof (induct arbitrary: P')
      case (encR S)
      assume "SourceTerm S (STCal Source Target)* P'"
      from this obtain S' where A1: "S Source* S'" and A2: "S' ∈S P'"
        by (auto simp add: STCal_steps(1))
      from A1 oc obtain T where A3: "S Target* T" and A4: "(S', T)  TRel"
        by blast
      from A3 have "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
        by (simp add: STCal_steps(2))
      moreover have "P' ∼⟦⋅⟧T<TRel> TargetTerm T"
      proof -
        from A2 have "P' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (simp add: indRelTEQ.encR)
        moreover from A4 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> TargetTerm T"
          by (rule indRelTEQ.target)
        ultimately show "P' ∼⟦⋅⟧T<TRel> TargetTerm T"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "Q'. TargetTerm (S) (STCal Source Target)* Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (encL S)
      assume "TargetTerm (S) (STCal Source Target)* P'"
      from this obtain T where B1: "S Target* T" and B2: "T ∈T P'"
        by (auto simp add: STCal_steps(2))
      from B1 oc obtain S' where B3: "S Source* S'" and B4: "(S', T)  TRel"
        by blast
      from B3 have "SourceTerm S (STCal Source Target)* (SourceTerm S')"
        by (simp add: STCal_steps(1))
      moreover have "P' ∼⟦⋅⟧T<TRel> SourceTerm S'"
      proof -
        from B4 eqT have "(T, S')  TRel"
            unfolding equiv_def sym_def
          by blast
        with B2 have "P' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (simp add: indRelTEQ.target)
        moreover have "TargetTerm (S') ∼⟦⋅⟧T<TRel> SourceTerm S'"
          by (rule indRelTEQ.encL)
        ultimately show "P' ∼⟦⋅⟧T<TRel> SourceTerm S'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "Q'. SourceTerm S (STCal Source Target)* Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T1 (STCal Source Target)* P'"
      from this obtain T1' where C1: "T1 Target* T1'" and C2: "T1' ∈T P'"
        by (auto simp add: STCal_steps(2))
      assume "(T1, T2)  TRel"
      with C1 bisimT obtain T2' where C3: "T2 Target* T2'" and C4: "(T1', T2')  TRel"
        by blast
      from C3 have "TargetTerm T2 (STCal Source Target)* (TargetTerm T2')"
        by (simp add: STCal_steps(2))
      moreover from C2 C4 have "P' ∼⟦⋅⟧T<TRel> TargetTerm T2'"
        by (simp add: indRelTEQ.target)
      ultimately show "Q'. TargetTerm T2 (STCal Source Target)* Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (trans P Q R)
      assume "P (STCal Source Target)* P'"
         and "P'. P (STCal Source Target)* P'
               Q'. Q (STCal Source Target)* Q'  P' ∼⟦⋅⟧T<TRel> Q'"
      from this obtain Q' where D1: "Q (STCal Source Target)* Q'" and D2: "P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
      assume "Q'. Q (STCal Source Target)* Q'
               R'. R (STCal Source Target)* R'  Q' ∼⟦⋅⟧T<TRel> R'"
      with D1 obtain R' where D3: "R (STCal Source Target)* R'" and D4: "Q' ∼⟦⋅⟧T<TRel> R'"
        by blast
      from D2 D4 have "P' ∼⟦⋅⟧T<TRel> R'"
        by (rule indRelTEQ.trans)
      with D3 show "R'. R (STCal Source Target)* R'  P' ∼⟦⋅⟧T<TRel> R'"
        by blast
    qed
  next
    fix P Q Q'
    assume "P ∼⟦⋅⟧T<TRel> Q" and "Q (STCal Source Target)* Q'"
    thus "P'. P (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> Q'"
    proof (induct arbitrary: Q')
      case (encR S)
      assume "TargetTerm (S) (STCal Source Target)* Q'"
      from this obtain T where E1: "S Target* T" and E2: "T ∈T Q'"
        by (auto simp add: STCal_steps(2))
      from E1 oc obtain S' where E3: "S Source* S'" and E4: "(S', T)  TRel"
        by blast
      from E3 have "SourceTerm S (STCal Source Target)* (SourceTerm S')"
        by (simp add: STCal_steps(1))
      moreover have "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
      proof -
        have "SourceTerm S' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (rule indRelTEQ.encR)
        moreover from E2 E4 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> Q'"
          by (simp add: indRelTEQ.target)
        ultimately show "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "P'. SourceTerm S (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (encL S)
      assume "SourceTerm S (STCal Source Target)* Q'"
      from this obtain S' where F1: "S Source* S'" and F2: "S' ∈S Q'"
        by (auto simp add: STCal_steps(1))
      from F1 oc obtain T where F3: "S Target* T" and F4: "(S', T)  TRel"
        by blast
      from F3 have "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
        by (simp add: STCal_steps(2))
      moreover have "TargetTerm T ∼⟦⋅⟧T<TRel> Q'"
      proof -
        from F4 eqT have "(T, S')  TRel"
            unfolding equiv_def sym_def
          by blast
        hence "TargetTerm T ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (rule indRelTEQ.target)
        moreover from F2 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> Q'"
          by (simp add: indRelTEQ.encL)
        ultimately show "TargetTerm T ∼⟦⋅⟧T<TRel> Q'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "P'. TargetTerm (S) (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T2 (STCal Source Target)* Q'"
      from this obtain T2' where G1: "T2 Target* T2'" and G2: "T2' ∈T Q'"
        by (auto simp add: STCal_steps(2))
      assume "(T1, T2)  TRel"
      with G1 bisimT obtain T1' where G3: "T1 Target* T1'" and G4: "(T1', T2')  TRel"
        by blast
      from G3 have "TargetTerm T1 (STCal Source Target)* (TargetTerm T1')"
        by (simp add: STCal_steps(2))
      moreover from G2 G4 have "TargetTerm T1' ∼⟦⋅⟧T<TRel> Q'"
        by (simp add: indRelTEQ.target)
      ultimately show "P'. TargetTerm T1 (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (trans P Q R R')
      assume "R (STCal Source Target)* R'"
         and "R'. R (STCal Source Target)* R'
               Q'. Q (STCal Source Target)* Q'  Q' ∼⟦⋅⟧T<TRel> R'"
      from this obtain Q' where H1: "Q (STCal Source Target)* Q'" and H2: "Q' ∼⟦⋅⟧T<TRel> R'"
        by blast
      assume "Q'. Q (STCal Source Target)* Q'
               P'. P (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> Q'"
      with H1 obtain P' where H3: "P (STCal Source Target)* P'" and H4: "P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
      from H4 H2 have "P' ∼⟦⋅⟧T<TRel> R'"
        by (rule indRelTEQ.trans)
      with H3 show "P'. P (STCal Source Target)* P'  P' ∼⟦⋅⟧T<TRel> R'"
        by blast
    qed
  qed
next
  assume bisim: "weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  have "operational_corresponding TRel"
  proof auto
    fix S S'
    have "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
      by (rule indRelTEQ.encR)
    moreover assume "S Source* S'"
    hence "SourceTerm S (STCal Source Target)* (SourceTerm S')"
      by (simp add: STCal_steps(1))
    ultimately obtain Q' where I1: "TargetTerm (S) (STCal Source Target)* Q'"
                           and I2: "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
        using bisim
      by blast
    from I1 obtain T where I3: "S Target* T" and I4: "T ∈T Q'"
      by (auto simp add: STCal_steps(2))
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with I2 I4 have "(S', T)  TRel"
        using indRelTEQ_to_TRel(2)[where TRel="TRel"]
              trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      by simp
    with I3 show "T. S Target* T  (S', T)  TRel"
      by blast
  next
    fix S T
    have "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
      by (rule indRelTEQ.encR)
    moreover assume "S Target* T"
    hence "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
      by (simp add: STCal_steps(2))
    ultimately obtain Q' where J1: "SourceTerm S (STCal Source Target)* Q'"
                           and J2: "Q' ∼⟦⋅⟧T<TRel> TargetTerm T"
        using bisim
      by blast
    from J1 obtain S' where J3: "S Source* S'" and J4: "S' ∈S Q'"
      by (auto simp add: STCal_steps(1))
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with J2 J4 have "(S', T)  TRel"
        using indRelTEQ_to_TRel(2)[where TRel="TRel"]
              trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      by blast
    with J3 show "S'. S Source* S'  (S', T)  TRel"
      by blast
  qed
  moreover have "weak_reduction_bisimulation TRel Target"
  proof -
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with bisim show "weak_reduction_bisimulation TRel Target"
        using indRelTEQ_impl_TRel_is_weak_reduction_bisimulation[where TRel="TRel"]
      by simp
  qed
  ultimately show "operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
    by simp
qed

lemma (in encoding) OC_wrt_equivalence_iff_weak_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes eqT: "equivalence TRel"
  shows "(operational_corresponding TRel  weak_reduction_bisimulation TRel Target)  (Rel.
         (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
          trans Rel  weak_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  assume oc: "operational_corresponding TRel" and bisimT: "weak_reduction_bisimulation TRel Target"
  from eqT have rt: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding equiv_def refl_on_def
    by auto
  have "S. SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)  TargetTerm (S) ∼⟦⋅⟧T<TRel> SourceTerm S"
    by (simp add: indRelTEQ.encR indRelTEQ.encL)
  moreover from rt have "TRel = {(T1, T2). TargetTerm T1 ∼⟦⋅⟧T<TRel> TargetTerm T2}"
      using indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by (auto simp add: indRelTEQ.target)
  moreover have "trans (indRelTEQ TRel)"
      using indRelTEQ.trans[where TRel="TRel"]
      unfolding trans_def
    by blast
  moreover from eqT oc bisimT
  have "weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
      using OC_wrt_equivalence_iff_indRelTEQ_weak_reduction_bisimulation[where TRel="TRel"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
         weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
                  (TargetTerm (S), SourceTerm S)  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
           weak_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel
                                   (TargetTerm (S), SourceTerm S)  Rel"
   and A2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}" and A3: "trans Rel"
   and A4: "weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  have "operational_corresponding TRel"
  proof auto
    fix S S'
    from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover assume "S Source* S'"
    hence "SourceTerm S (STCal Source Target)* (SourceTerm S')"
      by (simp add: STCal_steps(1))
    ultimately obtain Q' where B1: "TargetTerm (S) (STCal Source Target)* Q'"
                           and B2: "(SourceTerm S', Q')  Rel"
        using A4
      by blast
    from B1 obtain T where B3: "S Target* T" and B4: "T ∈T Q'"
      by (auto simp add: STCal_steps(2))
    from A1 have "(TargetTerm (S'), SourceTerm S')  Rel"
      by simp
    with B2 A3 have "(TargetTerm (S'), Q')  Rel"
        unfolding trans_def
      by blast
    with B4 A2 have "(S', T)  TRel"
      by simp
    with B3 show "T. S Target* T  (S', T)  TRel"
      by blast
  next
    fix S T
    from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover assume "S Target* T"
    hence "TargetTerm (S) (STCal Source Target)* (TargetTerm T)"
      by (simp add: STCal_steps(2))
    ultimately obtain P' where C1: "SourceTerm S (STCal Source Target)* P'"
                           and C2: "(P', TargetTerm T)  Rel"
        using A4
      by blast
    from C1 obtain S' where C3: "S Source* S'" and C4: "S' ∈S P'"
      by (auto simp add: STCal_steps(1))
    from A1 C4 have "(TargetTerm (S'), P')  Rel"
      by simp
    from A3 this C2 have "(TargetTerm (S'), TargetTerm T)  Rel"
        unfolding trans_def
      by blast
    with A2 have "(S', T)  TRel"
      by simp
    with C3 show "S'. S Source* S'  (S', T)  TRel"
      by blast
  qed
  moreover have "weak_reduction_bisimulation TRel Target"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with A2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP Target* TP'"
    hence "TargetTerm TP (STCal Source Target)* (TargetTerm TP')"
      by (simp add: STCal_steps(2))
    ultimately obtain Q' where D1: "TargetTerm TQ (STCal Source Target)* Q'"
                           and D2: "(TargetTerm TP', Q')  Rel"
        using A4
      by blast
    from D1 obtain TQ' where D3: "TQ Target* TQ'" and D4: "TQ' ∈T Q'"
      by (auto simp add: STCal_steps(2))
    from A2 D2 D4 have "(TP', TQ')  TRel"
      by simp
    with D3 show "TQ'. TQ Target* TQ'  (TP', TQ')  TRel"
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with A2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ Target* TQ'"
    hence "TargetTerm TQ (STCal Source Target)* (TargetTerm TQ')"
      by (simp add: STCal_steps(2))
    ultimately obtain P' where E1: "TargetTerm TP (STCal Source Target)* P'"
                           and E2: "(P', TargetTerm TQ')  Rel"
        using A4
      by blast
    from E1 obtain TP' where E3: "TP Target* TP'" and E4: "TP' ∈T P'"
      by (auto simp add: STCal_steps(2))
    from A2 E2 E4 have "(TP', TQ')  TRel"
      by simp
    with E3 show "TP'. TP Target* TP'  (TP', TQ')  TRel"
      by blast
  qed
  ultimately show "operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
    by simp
qed

text ‹An encoding is strong operational corresponding w.r.t a strong bisimulation on target terms
        TRel iff there exists a relation, like indRelRTPO, that relates at least all source terms
        and their literal translations, includes TRel, and is a strong bisimulation. Thus this
        variant of operational correspondence ensures that source terms and their translations are
        strong bisimilar.›

lemma (in encoding) SOC_iff_indRelRTPO_is_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding (TRel*)
          strong_reduction_bisimulation (TRel+) Target)
         = strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume ocorr: "strongly_operational_corresponding (TRel*)"
     and bisim: "strong_reduction_bisimulation (TRel+) Target"
  hence "strong_reduction_simulation (indRelRTPO TRel) (STCal Source Target)"
      using SOCom_iff_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  moreover from bisim have "strong_reduction_simulation ((TRel+)¯) Target"
      using strong_reduction_bisimulations_impl_inverse_is_simulation[where Rel="TRel+"]
    by simp
  with ocorr
  have "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using SOSou_iff_inverse_of_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using strong_reduction_simulations_impl_bisimulation[where Rel="indRelRTPO TRel"]
    by simp
next
  assume bisim: "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
  hence "strongly_operational_complete (TRel*)  strong_reduction_simulation (TRel+) Target"
      using SOCom_iff_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  moreover from bisim
  have "strong_reduction_simulation ((indRelRTPO TRel)¯) (STCal Source Target)"
      using strong_reduction_bisimulations_impl_inverse_is_simulation[where Rel="indRelRTPO TRel"]
    by simp
  hence "strongly_operational_sound (TRel*)  strong_reduction_simulation ((TRel+)¯) Target"
      using SOSou_iff_inverse_of_indRelRTPO_is_strong_reduction_simulation[where TRel="TRel"]
    by simp
  ultimately show "strongly_operational_corresponding (TRel*)
                    strong_reduction_bisimulation (TRel+) Target"
      using strong_reduction_simulations_impl_bisimulation[where Rel="TRel+"]
    by simp
qed

lemma (in encoding) SOC_iff_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding (TRel*)
          strong_reduction_bisimulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             strong_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "T1 T2. (T1, T2)  TRel  TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2"
    by (simp add: indRelRTPO.target)
  moreover have "T1 T2. TargetTerm T1 ≲⟦⋅⟧RT<TRel> TargetTerm T2  (T1, T2)  TRel+"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by simp
  moreover have "S T. SourceTerm S ≲⟦⋅⟧RT<TRel> TargetTerm T  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] trans_closure_of_TRel_refl_cond
    by simp
  moreover assume "strongly_operational_corresponding (TRel*)"
              and "strong_reduction_bisimulation (TRel+) Target"
  hence "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           strong_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and A2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and A3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and A4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
   and A5: "strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "strongly_operational_complete (TRel*)
          strong_reduction_simulation (TRel+) Target"
      using SOCom_iff_strong_reduction_simulation[where TRel="TRel"]
    by blast
  moreover from A5 have "strong_reduction_simulation (Rel¯) (STCal Source Target)"
      using strong_reduction_bisimulations_impl_inverse_is_simulation[where Rel="Rel"]
    by simp
  with A1 A2 A3 A4 have "strongly_operational_sound (TRel*)
                          strong_reduction_simulation ((TRel+)¯) Target"
      using SOSou_iff_strong_reduction_simulation[where TRel="TRel"]
    by blast
  ultimately show "strongly_operational_corresponding (TRel*)
                    strong_reduction_bisimulation (TRel+) Target"
      using strong_reduction_simulations_impl_bisimulation[where Rel="TRel+"]
    by simp
qed

lemma (in encoding) SOC_wrt_preorder_iff_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding TRel  preorder TRel
          strong_reduction_bisimulation TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             preorder Rel
             strong_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE, erule conjE, erule conjE)
  assume A1: "strongly_operational_complete TRel" and A2: "strongly_operational_sound TRel"
     and A3:"preorder TRel" and A4: "strong_reduction_bisimulation TRel Target"
  from A3 have A5: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  with A3 have "TRel* = TRel"
      using reflcl_trancl[of TRel]
      unfolding preorder_on_def refl_on_def
    by blast
  with A1 A2 have "strongly_operational_corresponding (TRel*)"
    by simp
  moreover from A4 A5 have "strong_reduction_bisimulation (TRel+) Target"
    by simp
  ultimately
  have "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by blast
  moreover have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover
  have "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  indRelRTPO TRel}"
  proof auto
    fix TP TQ
    assume "(TP, TQ)  TRel"
    thus "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
      by (rule indRelRTPO.target)
  next
    fix TP TQ
    assume "TargetTerm TP ≲⟦⋅⟧RT<TRel> TargetTerm TQ"
    with A3 show "(TP, TQ)  TRel"
        using indRelRTPO_to_TRel(4)[where TRel="TRel"] trancl_id[of TRel]
        unfolding preorder_on_def
      by blast
  qed
  moreover from A3
  have "S T. (SourceTerm S, TargetTerm T)  indRelRTPO TRel  (S, T)  TRel+"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"] reflcl_trancl[of TRel]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      unfolding preorder_on_def refl_on_def
    by blast
  with A3 have "S T. (SourceTerm S, TargetTerm T)  indRelRTPO TRel  (S, T)  TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  moreover from A3 have "refl (indRelRTPO TRel)"
      unfolding preorder_on_def
    by (simp add: indRelRTPO_refl)
  moreover have "trans (indRelRTPO TRel)"
      using indRelRTPO.trans
      unfolding trans_def
    by blast
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
                    preorder Rel
                    strong_reduction_bisimulation Rel (STCal Source Target)"
      unfolding preorder_on_def
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           preorder Rel
           strong_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel" and B4: "preorder Rel"
   and B5: "strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  from B2 B4 have B6: "refl TRel"
      unfolding preorder_on_def refl_on_def
    by blast
  from B2 B4 have B7: "trans TRel"
      unfolding trans_def preorder_on_def
    by blast
  hence B8: "TRel+ = TRel"
    by (rule trancl_id)
  with B6 have B9: "TRel* = TRel"
      using reflcl_trancl[of TRel]
      unfolding refl_on_def
    by blast
  with B3 have "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    by simp
  moreover from B2 B8 have "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by auto
  ultimately have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
    strong_reduction_bisimulation Rel (STCal Source Target)"
      using B1 B5
    by blast
  hence "strongly_operational_corresponding (TRel*)  strong_reduction_bisimulation (TRel+) Target"
      using SOC_iff_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  with B8 B9
  have "strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target"
    by simp
  moreover from B6 B7 have "preorder TRel"
      unfolding preorder_on_def
    by blast
  ultimately show "strongly_operational_corresponding TRel  preorder TRel
                    strong_reduction_bisimulation TRel Target"
    by blast
qed

lemma (in encoding) SOC_wrt_TRel_iff_strong_reduction_bisimulation:
  shows "(TRel. strongly_operational_corresponding (TRel*)
          strong_reduction_bisimulation (TRel+) Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (S T. (SourceTerm S, TargetTerm T)  Rel
                (TargetTerm (S), TargetTerm T)  Rel=)
             strong_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI)
  assume "TRel. strongly_operational_corresponding (TRel*)
           strong_reduction_bisimulation (TRel+) Target"
  from this obtain TRel where "strongly_operational_corresponding (TRel*)"
                          and "strong_reduction_bisimulation (TRel+) Target"
    by blast
  hence "strong_reduction_bisimulation (indRelRTPO TRel) (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "S. (SourceTerm S, TargetTerm (S))  indRelRTPO TRel"
    by (simp add: indRelRTPO.encR)
  moreover have "S T. (SourceTerm S, TargetTerm T)  (indRelRTPO TRel)
                  (TargetTerm (S), TargetTerm T)  (indRelRTPO TRel)="
      using indRelRTPO_relates_source_target[where TRel="TRel"]
    by simp
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (TargetTerm (S), TargetTerm T)  Rel=)
    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (TargetTerm (S), TargetTerm T)  Rel=)
    strong_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "S T. (SourceTerm S, TargetTerm T)  Rel
                                   (TargetTerm (S), TargetTerm T)  Rel="
                         and A3: "strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  from A2 obtain TRel where "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using target_relation_from_source_target_relation[where Rel="Rel"]
    by blast
  with A1 A3 have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
                    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
                    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
                    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "strongly_operational_corresponding (TRel*)
          strong_reduction_bisimulation (TRel+) Target"
      using SOC_iff_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  thus "TRel. strongly_operational_corresponding (TRel*)
         strong_reduction_bisimulation (TRel+) Target"
    by blast
qed

lemma (in encoding) SOC_wrt_equivalence_iff_indRelTEQ_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes eqT: "equivalence TRel"
  shows "(strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target)
          strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
proof (rule iffI, erule conjE)
  assume oc:     "strongly_operational_corresponding TRel"
     and bisimT: "strong_reduction_bisimulation TRel Target"
  show "strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  proof auto
    fix P Q P'
    assume "P ∼⟦⋅⟧T<TRel> Q" and "P (STCal Source Target) P'"
    thus "Q'. Q (STCal Source Target) Q'  P' ∼⟦⋅⟧T<TRel> Q'"
    proof (induct arbitrary: P')
      case (encR S)
      assume "SourceTerm S (STCal Source Target) P'"
      from this obtain S' where A1: "S Source S'" and A2: "S' ∈S P'"
        by (auto simp add: STCal_step(1))
      from A1 oc obtain T where A3: "S Target T" and A4: "(S', T)  TRel"
        by blast
      from A3 have "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
        by (simp add: STCal_step(2))
      moreover have "P' ∼⟦⋅⟧T<TRel> TargetTerm T"
      proof -
        from A2 have "P' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (simp add: indRelTEQ.encR)
        moreover from A4 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> TargetTerm T"
          by (rule indRelTEQ.target)
        ultimately show "P' ∼⟦⋅⟧T<TRel> TargetTerm T"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "Q'. TargetTerm (S) (STCal Source Target) Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (encL S)
      assume "TargetTerm (S) (STCal Source Target) P'"
      from this obtain T where B1: "S Target T" and B2: "T ∈T P'"
        by (auto simp add: STCal_step(2))
      from B1 oc obtain S' where B3: "S Source S'" and B4: "(S', T)  TRel"
        by blast
      from B3 have "SourceTerm S (STCal Source Target) (SourceTerm S')"
        by (simp add: STCal_step(1))
      moreover have "P' ∼⟦⋅⟧T<TRel> SourceTerm S'"
      proof -
        from B4 eqT have "(T, S')  TRel"
            unfolding equiv_def sym_def
          by blast
        with B2 have "P' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (simp add: indRelTEQ.target)
        moreover have "TargetTerm (S') ∼⟦⋅⟧T<TRel> SourceTerm S'"
          by (rule indRelTEQ.encL)
        ultimately show "P' ∼⟦⋅⟧T<TRel> SourceTerm S'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "Q'. SourceTerm S (STCal Source Target) Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T1 (STCal Source Target) P'"
      from this obtain T1' where C1: "T1 Target T1'" and C2: "T1' ∈T P'"
        by (auto simp add: STCal_step(2))
      assume "(T1, T2)  TRel"
      with C1 bisimT obtain T2' where C3: "T2 Target T2'" and C4: "(T1', T2')  TRel"
        by blast
      from C3 have "TargetTerm T2 (STCal Source Target) (TargetTerm T2')"
        by (simp add: STCal_step(2))
      moreover from C2 C4 have "P' ∼⟦⋅⟧T<TRel> TargetTerm T2'"
        by (simp add: indRelTEQ.target)
      ultimately show "Q'. TargetTerm T2 (STCal Source Target) Q'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (trans P Q R)
      assume "P (STCal Source Target) P'"
         and "P'. P (STCal Source Target) P'
               Q'. Q (STCal Source Target) Q'  P' ∼⟦⋅⟧T<TRel> Q'"
      from this obtain Q' where D1: "Q (STCal Source Target) Q'" and D2: "P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
      assume "Q'. Q (STCal Source Target) Q'
               R'. R (STCal Source Target) R'  Q' ∼⟦⋅⟧T<TRel> R'"
      with D1 obtain R' where D3: "R (STCal Source Target) R'" and D4: "Q' ∼⟦⋅⟧T<TRel> R'"
        by blast
      from D2 D4 have "P' ∼⟦⋅⟧T<TRel> R'"
        by (rule indRelTEQ.trans)
      with D3 show "R'. R (STCal Source Target) R'  P' ∼⟦⋅⟧T<TRel> R'"
        by blast
    qed
  next
    fix P Q Q'
    assume "P ∼⟦⋅⟧T<TRel> Q" and "Q (STCal Source Target) Q'"
    thus "P'. P (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> Q'"
    proof (induct arbitrary: Q')
      case (encR S)
      assume "TargetTerm (S) (STCal Source Target) Q'"
      from this obtain T where E1: "S Target T" and E2: "T ∈T Q'"
        by (auto simp add: STCal_step(2))
      from E1 oc obtain S' where E3: "S Source S'" and E4: "(S', T)  TRel"
        by blast
      from E3 have "SourceTerm S (STCal Source Target) (SourceTerm S')"
        by (simp add: STCal_step(1))
      moreover have "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
      proof -
        have "SourceTerm S' ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (rule indRelTEQ.encR)
        moreover from E2 E4 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> Q'"
          by (simp add: indRelTEQ.target)
        ultimately show "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "P'. SourceTerm S (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (encL S)
      assume "SourceTerm S (STCal Source Target) Q'"
      from this obtain S' where F1: "S Source S'" and F2: "S' ∈S Q'"
        by (auto simp add: STCal_step(1))
      from F1 oc obtain T where F3: "S Target T" and F4: "(S', T)  TRel"
        by blast
      from F3 have "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
        by (simp add: STCal_step(2))
      moreover have "TargetTerm T ∼⟦⋅⟧T<TRel> Q'"
      proof -
        from F4 eqT have "(T, S')  TRel"
            unfolding equiv_def sym_def
          by blast
        hence "TargetTerm T ∼⟦⋅⟧T<TRel> TargetTerm (S')"
          by (rule indRelTEQ.target)
        moreover from F2 have "TargetTerm (S') ∼⟦⋅⟧T<TRel> Q'"
          by (simp add: indRelTEQ.encL)
        ultimately show "TargetTerm T ∼⟦⋅⟧T<TRel> Q'"
          by (rule indRelTEQ.trans)
      qed
      ultimately show "P'. TargetTerm (S) (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (target T1 T2)
      assume "TargetTerm T2 (STCal Source Target) Q'"
      from this obtain T2' where G1: "T2 Target T2'" and G2: "T2' ∈T Q'"
        by (auto simp add: STCal_step(2))
      assume "(T1, T2)  TRel"
      with G1 bisimT obtain T1' where G3: "T1 Target T1'" and G4: "(T1', T2')  TRel"
        by blast
      from G3 have "TargetTerm T1 (STCal Source Target) (TargetTerm T1')"
        by (simp add: STCal_step(2))
      moreover from G2 G4 have "TargetTerm T1' ∼⟦⋅⟧T<TRel> Q'"
        by (simp add: indRelTEQ.target)
      ultimately show "P'. TargetTerm T1 (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
    next
      case (trans P Q R R')
      assume "R (STCal Source Target) R'"
         and "R'. R (STCal Source Target) R'
               Q'. Q (STCal Source Target) Q'  Q' ∼⟦⋅⟧T<TRel> R'"
      from this obtain Q' where H1: "Q (STCal Source Target) Q'" and H2: "Q' ∼⟦⋅⟧T<TRel> R'"
        by blast
      assume "Q'. Q (STCal Source Target) Q'
               P'. P (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> Q'"
      with H1 obtain P' where H3: "P (STCal Source Target) P'" and H4: "P' ∼⟦⋅⟧T<TRel> Q'"
        by blast
      from H4 H2 have "P' ∼⟦⋅⟧T<TRel> R'"
        by (rule indRelTEQ.trans)
      with H3 show "P'. P (STCal Source Target) P'  P' ∼⟦⋅⟧T<TRel> R'"
        by blast
    qed
  qed
next
  assume bisim: "strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
  have "strongly_operational_corresponding TRel"
  proof auto
    fix S S'
    have "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
      by (rule indRelTEQ.encR)
    moreover assume "S Source S'"
    hence "SourceTerm S (STCal Source Target) (SourceTerm S')"
      by (simp add: STCal_step(1))
    ultimately obtain Q' where I1: "TargetTerm (S) (STCal Source Target) Q'"
                           and I2: "SourceTerm S' ∼⟦⋅⟧T<TRel> Q'"
        using bisim
      by blast
    from I1 obtain T where I3: "S Target T" and I4: "T ∈T Q'"
      by (auto simp add: STCal_step(2))
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with I2 I4 have "(S', T)  TRel"
        using indRelTEQ_to_TRel(2)[where TRel="TRel"]
              trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      by simp
    with I3 show "T. S Target T  (S', T)  TRel"
      by blast
  next
    fix S T
    have "SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)"
      by (rule indRelTEQ.encR)
    moreover assume "S Target T"
    hence "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
      by (simp add: STCal_step(2))
    ultimately obtain Q' where J1: "SourceTerm S (STCal Source Target) Q'"
                           and J2: "Q' ∼⟦⋅⟧T<TRel> TargetTerm T"
        using bisim
      by blast
    from J1 obtain S' where J3: "S Source S'" and J4: "S' ∈S Q'"
      by (auto simp add: STCal_step(1))
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with J2 J4 have "(S', T)  TRel"
        using indRelTEQ_to_TRel(2)[where TRel="TRel"]
              trans_closure_of_TRel_refl_cond[where TRel="TRel"]
      by blast
    with J3 show "S'. S Source S'  (S', T)  TRel"
      by blast
  qed
  moreover have "strong_reduction_bisimulation TRel Target"
  proof -
    from eqT have "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    with bisim show "strong_reduction_bisimulation TRel Target"
        using indRelTEQ_impl_TRel_is_strong_reduction_bisimulation[where TRel="TRel"]
      by simp
  qed
  ultimately
  show "strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target"
    by simp
qed

lemma (in encoding) SOC_wrt_equivalence_iff_strong_reduction_bisimulation:
  fixes TRel :: "('procT × 'procT) set"
  assumes eqT: "equivalence TRel"
  shows "(strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target)
          (Rel.
         (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
          trans Rel  strong_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE)
  assume oc:     "strongly_operational_corresponding TRel"
     and bisimT: "strong_reduction_bisimulation TRel Target"
  from eqT have rt: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding equiv_def refl_on_def
    by auto
  have "S. SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)  TargetTerm (S) ∼⟦⋅⟧T<TRel> SourceTerm S"
    by (simp add: indRelTEQ.encR indRelTEQ.encL)
  moreover from rt have "TRel = {(T1, T2). TargetTerm T1 ∼⟦⋅⟧T<TRel> TargetTerm T2}"
      using indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by (auto simp add: indRelTEQ.target)
  moreover have "trans (indRelTEQ TRel)"
      using indRelTEQ.trans[where TRel="TRel"]
      unfolding trans_def
    by blast
  moreover from eqT oc bisimT
  have "strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
      using SOC_wrt_equivalence_iff_indRelTEQ_strong_reduction_bisimulation[where TRel="TRel"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
         strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
                  (TargetTerm (S), SourceTerm S)  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
           strong_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel
                                   (TargetTerm (S), SourceTerm S)  Rel"
   and A2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}" and A3: "trans Rel"
   and A4: "strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  have "strongly_operational_corresponding TRel"
  proof auto
    fix S S'
    from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover assume "S Source S'"
    hence "SourceTerm S (STCal Source Target) (SourceTerm S')"
      by (simp add: STCal_step(1))
    ultimately obtain Q' where B1: "TargetTerm (S) (STCal Source Target) Q'"
                           and B2: "(SourceTerm S', Q')  Rel"
        using A4
      by blast
    from B1 obtain T where B3: "S Target T" and B4: "T ∈T Q'"
      by (auto simp add: STCal_step(2))
    from A1 have "(TargetTerm (S'), SourceTerm S')  Rel"
      by simp
    with B2 A3 have "(TargetTerm (S'), Q')  Rel"
        unfolding trans_def
      by blast
    with B4 A2 have "(S', T)  TRel"
      by simp
    with B3 show "T. S Target T  (S', T)  TRel"
      by blast
  next
    fix S T
    from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover assume "S Target T"
    hence "TargetTerm (S) (STCal Source Target) (TargetTerm T)"
      by (simp add: STCal_step(2))
    ultimately obtain P' where C1: "SourceTerm S (STCal Source Target) P'"
                           and C2: "(P', TargetTerm T)  Rel"
        using A4
      by blast
    from C1 obtain S' where C3: "S Source S'" and C4: "S' ∈S P'"
      by (auto simp add: STCal_step(1))
    from A1 C4 have "(TargetTerm (S'), P')  Rel"
      by simp
    from A3 this C2 have "(TargetTerm (S'), TargetTerm T)  Rel"
        unfolding trans_def
      by blast
    with A2 have "(S', T)  TRel"
      by simp
    with C3 show "S'. S Source S'  (S', T)  TRel"
      by blast
  qed
  moreover have "strong_reduction_bisimulation TRel Target"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with A2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP Target TP'"
    hence "TargetTerm TP (STCal Source Target) (TargetTerm TP')"
      by (simp add: STCal_step(2))
    ultimately obtain Q' where D1: "TargetTerm TQ (STCal Source Target) Q'"
                           and D2: "(TargetTerm TP', Q')  Rel"
        using A4
      by blast
    from D1 obtain TQ' where D3: "TQ Target TQ'" and D4: "TQ' ∈T Q'"
      by (auto simp add: STCal_step(2))
    from A2 D2 D4 have "(TP', TQ')  TRel"
      by simp
    with D3 show "TQ'. TQ Target TQ'  (TP', TQ')  TRel"
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with A2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ Target TQ'"
    hence "TargetTerm TQ (STCal Source Target) (TargetTerm TQ')"
      by (simp add: STCal_step(2))
    ultimately obtain P' where E1: "TargetTerm TP (STCal Source Target) P'"
                           and E2: "(P', TargetTerm TQ')  Rel"
        using A4
      by blast
    from E1 obtain TP' where E3: "TP Target TP'" and E4: "TP' ∈T P'"
      by (auto simp add: STCal_step(2))
    from A2 E2 E4 have "(TP', TQ')  TRel"
      by simp
    with E3 show "TP'. TP Target TP'  (TP', TQ')  TRel"
      by blast
  qed
  ultimately
  show "strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target"
    by simp
qed

end

Theory FullAbstraction

theory FullAbstraction
  imports SourceTargetRelation
begin

section ‹Full Abstraction›

text ‹An encoding is fully abstract w.r.t. some source term relation SRel and some target term
        relation TRel if two source terms S1 and S2 form a pair (S1, S2) in SRel iff their literal
        translations form a pair (enc S1, enc S2) in TRel.›

abbreviation (in encoding) fully_abstract
    :: "('procS × 'procS) set  ('procT × 'procT) set  bool"
  where
  "fully_abstract SRel TRel  S1 S2. (S1, S2)  SRel  (S1, S2)  TRel"

subsection ‹Trivial Full Abstraction Results›

text ‹We start with some trivial full abstraction results. Each injective encoding is fully
        abstract w.r.t. to the identity relation on the source and the identity relation on the
        target.›

lemma (in encoding) inj_enc_is_fully_abstract_wrt_identities:
  assumes injectivity: "S1 S2. S1 = S2  S1 = S2"
  shows "fully_abstract {(S1, S2). S1 = S2} {(T1, T2). T1 = T2}"
    by (auto simp add: injectivity)

text ‹Each encoding is fully abstract w.r.t. the empty relation on the source and the target.›

lemma (in encoding) fully_abstract_wrt_empty_relation:
  shows "fully_abstract {} {}"
    by auto

text ‹Similarly, each encoding is fully abstract w.r.t. the all-relation on the source and the
        target.›

lemma (in encoding) fully_abstract_wrt_all_relation:
  shows "fully_abstract {(S1, S2). True} {(T1, T2). True}"
    by auto

text ‹If the encoding is injective then for each source term relation RelS there exists a target
        term relation RelT such that the encoding is fully abstract w.r.t. RelS and RelT.›

lemma (in encoding) fully_abstract_wrt_source_relation:
  fixes RelS :: "('procS × 'procS) set"
  assumes injectivity: "S1 S2. S1 = S2  S1 = S2"
  shows "RelT. fully_abstract RelS RelT"
proof -
  define RelT where "RelT = {(T1, T2). S1 S2. (S1, S2)  RelS  T1 = S1  T2 = S2}"
  with injectivity have "fully_abstract RelS RelT"
    by blast
  thus "RelT. fully_abstract RelS RelT"
    by blast
qed

text ‹If all source terms that are translated to the same target term are related by a trans
        source term relation RelS, then there exists a target term relation RelT such that the
        encoding is fully abstract w.r.t. RelS and RelT.›

lemma (in encoding) fully_abstract_wrt_trans_source_relation:
  fixes RelS :: "('procS × 'procS) set"
  assumes encRelS: "S1 S2. S1 = S2  (S1, S2)  RelS"
      and transS:  "trans RelS"
  shows "RelT. fully_abstract RelS RelT"
proof -
  define RelT where "RelT = {(T1, T2). S1 S2. (S1, S2)  RelS  T1 = S1  T2 = S2}"
  have "fully_abstract RelS RelT"
  proof auto
    fix S1 S2
    assume "(S1, S2)  RelS"
    with RelT_def show "(S1, S2)  RelT"
      by blast
  next
    fix S1 S2
    assume "(S1, S2)  RelT"
    with RelT_def obtain S1' S2' where A1: "(S1', S2')  RelS" and A2: "S1 = S1'"
                               and A3: "S2 = S2'"
      by blast
    from A2 encRelS have "(S1, S1')  RelS"
      by simp
    from this A1 transS have "(S1, S2')  RelS"
        unfolding trans_def
      by blast
    moreover from A3 encRelS have "(S2', S2)  RelS"
      by simp
    ultimately show "(S1, S2)  RelS"
        using transS
        unfolding trans_def
      by blast
  qed
  thus "RelT. fully_abstract RelS RelT"
    by blast
qed

lemma (in encoding) fully_abstract_wrt_trans_closure_of_source_relation:
  fixes RelS :: "('procS × 'procS) set"
  assumes encRelS: "S1 S2. S1 = S2  (S1, S2)  RelS+"
  shows "RelT. fully_abstract (RelS+) RelT"
      using encRelS trans_trancl[of RelS]
            fully_abstract_wrt_trans_source_relation[where RelS="RelS+"]
    by blast

text ‹For every encoding and every target term relation RelT there exists a source term relation
        RelS such that the encoding is fully abstract w.r.t. RelS and RelT.›

lemma (in encoding) fully_abstract_wrt_target_relation:
  fixes RelT :: "('procT × 'procT) set"
  shows "RelS. fully_abstract RelS RelT"
proof -
  define RelS where "RelS = {(S1, S2). (S1, S2)  RelT}"
  hence "fully_abstract RelS RelT"
    by simp
  thus "RelS. fully_abstract RelS RelT"
    by blast
qed

subsection ‹Fully Abstract Encodings›

text ‹Thus, as long as we can choose one of the two relations, full abstraction is trivial. For
        fixed source and target term relations encodings are not trivially fully abstract. For all
        encodings and relations SRel and TRel we can construct a relation on the disjunctive union
        of source and target terms, whose reduction to source terms is SRel and whose reduction to
        target terms is TRel. But full abstraction ensures that each trans relation that
        relates source terms and their literal translations in both directions includes SRel iff it
        includes TRel restricted to translated source terms.›

lemma (in encoding) full_abstraction_and_trans_relation_contains_SRel_impl_TRel:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encR:    "S. (SourceTerm S, TargetTerm (S))  Rel"
      and srel:    "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and trans:   "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  shows "S1 S2. (S1, S2)  TRel  (TargetTerm (S1), TargetTerm (S2))  Rel"
proof auto
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  hence "(TargetTerm (S1), SourceTerm S1)  Rel'"
    by simp
  moreover assume "(S1, S2)  TRel"
  with fullAbs have "(S1, S2)  SRel"
    by simp
  with srel Rel'_def have "(SourceTerm S1, SourceTerm S2)  Rel'"
    by simp
  moreover from encR Rel'_def have "(SourceTerm S2, TargetTerm (S2))  Rel'"
    by simp
  ultimately show "(TargetTerm (S1), TargetTerm (S2))  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
next
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  from encR Rel'_def have "(SourceTerm S1, TargetTerm (S1))  Rel'"
    by simp
  moreover assume "(TargetTerm (S1), TargetTerm (S2))  Rel"
  with Rel'_def have "(TargetTerm (S1), TargetTerm (S2))  Rel'"
    by simp
  moreover from Rel'_def have "(TargetTerm (S2), SourceTerm S2)  Rel'"
    by simp
  ultimately have "(SourceTerm S1, SourceTerm S2)  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
  with srel have "(S1, S2)  SRel"
    by simp
  with fullAbs show "(S1, S2)  TRel"
    by simp
qed

lemma (in encoding) full_abstraction_and_trans_relation_contains_TRel_impl_SRel:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encR:    "S. (SourceTerm S, TargetTerm (S))  Rel"
      and trel:    "S1 S2. (S1, S2)  TRel  (TargetTerm (S1), TargetTerm (S2))  Rel"
      and trans:   "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  shows "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
proof auto
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  from encR Rel'_def have "(SourceTerm S1, TargetTerm (S1))  Rel'"
    by simp
  moreover assume "(S1, S2)  SRel"
  with fullAbs have "(S1, S2)  TRel"
    by simp
  with trel Rel'_def have "(TargetTerm (S1), TargetTerm (S2))  Rel'"
    by simp
  moreover from Rel'_def have "(TargetTerm (S2), SourceTerm S2)  Rel'"
    by simp
  ultimately show "(SourceTerm S1, SourceTerm S2)  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
next
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  hence "(TargetTerm (S1), SourceTerm S1)  Rel'"
    by simp
  moreover assume "(SourceTerm S1, SourceTerm S2)  Rel"
  with Rel'_def have "(SourceTerm S1, SourceTerm S2)  Rel'"
    by simp
  moreover from encR Rel'_def have "(SourceTerm S2, TargetTerm (S2))  Rel'"
    by simp
  ultimately have "(TargetTerm (S1), TargetTerm (S2))  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
  with trel have "(S1, S2)  TRel"
    by simp
  with fullAbs show "(S1, S2)  SRel"
    by simp
qed

lemma (in encoding) full_abstraction_impl_trans_relation_contains_SRel_iff_TRel:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encR:    "S. (SourceTerm S, TargetTerm (S))  Rel"
      and trans:   "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  shows "(S1 S2. (S1, S2)  TRel  (TargetTerm (S1), TargetTerm (S2))  Rel)
          (SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel})"
proof
  assume "S1 S2. ((S1, S2)  TRel) = ((TargetTerm (S1), TargetTerm (S2))  Rel)"
  thus "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      using assms full_abstraction_and_trans_relation_contains_TRel_impl_SRel[where
            SRel="SRel" and TRel="TRel"]
    by blast
next
  assume "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
  thus "S1 S2. (S1, S2)  TRel  (TargetTerm (S1), TargetTerm (S2))  Rel"
      using assms full_abstraction_and_trans_relation_contains_SRel_impl_TRel[where
            SRel="SRel" and TRel="TRel"]
    by blast
qed

lemma (in encoding) full_abstraction_impl_trans_relation_contains_SRel_iff_TRel_encRL:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encR:    "S. (SourceTerm S, TargetTerm (S))  Rel"
      and encL:    "S. (TargetTerm (S), SourceTerm S)  Rel"
      and trans:   "trans Rel"
  shows "(S1 S2. (S1, S2)  TRel  (TargetTerm (S1), TargetTerm (S2))  Rel)
          (SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel})"
proof -
  from encL have "Rel  {(P, Q). S. S ∈T P  S ∈S Q} = Rel"
    by auto
  with fullAbs encR trans show ?thesis
      using full_abstraction_impl_trans_relation_contains_SRel_iff_TRel[where Rel="Rel"
            and SRel="SRel" and TRel="TRel"]
    by simp
qed

text ‹Full abstraction ensures that SRel and TRel satisfy the same basic properties that can be
        defined on their pairs. In particular:
        (1) SRel is refl iff TRel reduced to translated source terms is refl
        (2) if the encoding is surjective then SRel is refl iff TRel is refl
        (3) SRel is sym iff TRel reduced to translated source terms is sym
        (4) SRel is trans iff TRel reduced to translated source terms is trans›

lemma (in encoding) full_abstraction_impl_SRel_iff_TRel_is_refl:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
  shows "refl SRel  (S. (S, S)  TRel)"
      unfolding refl_on_def
    by (simp add: fullAbs)

lemma (in encoding) full_abstraction_and_surjectivity_impl_SRel_iff_TRel_is_refl:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and surj:    "T. S. T = S"
  shows "refl SRel  refl TRel"
proof
  assume reflS: "refl SRel"
  show "refl TRel"
    unfolding refl_on_def
  proof auto
    fix T
    from surj obtain S where "T = S"
      by blast
    moreover from reflS have "(S, S)  SRel"
        unfolding refl_on_def
      by simp
    with fullAbs have "(S, S)  TRel"
      by simp
    ultimately show "(T, T)  TRel"
      by simp
  qed
next
  assume "refl TRel"
  with fullAbs show "refl SRel"
      unfolding refl_on_def
    by simp
qed

lemma (in encoding) full_abstraction_impl_SRel_iff_TRel_is_sym:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
  shows "sym SRel  sym {(T1, T2). S1 S2. T1 = S1  T2 = S2  (T1, T2)  TRel}"
      unfolding sym_def
    by (simp add: fullAbs, blast)

lemma (in encoding) full_abstraction_and_surjectivity_impl_SRel_iff_TRel_is_sym:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and surj:    "T. S. T = S"
  shows "sym SRel  sym TRel"
      using fullAbs surj
            full_abstraction_impl_SRel_iff_TRel_is_sym[where SRel="SRel" and TRel="TRel"]
    by auto

lemma (in encoding) full_abstraction_impl_SRel_iff_TRel_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
  shows "trans SRel  trans {(T1, T2). S1 S2. T1 = S1  T2 = S2  (T1, T2)  TRel}"
      unfolding trans_def
    by (simp add: fullAbs, blast)

lemma (in encoding) full_abstraction_and_surjectivity_impl_SRel_iff_TRel_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and surj:    "T. S. T = S"
  shows "trans SRel  trans TRel"
      using fullAbs surj
            full_abstraction_impl_SRel_iff_TRel_is_trans[where SRel="SRel" and TRel="TRel"]
    by auto

text ‹Similarly, a fully abstract encoding that respects a predicate ensures the this predicate
        is preserved, reflected, or respected by SRel iff it is preserved, reflected, or respected
        by TRel.›

lemma (in encoding) full_abstraction_and_enc_respects_pred_impl_SRel_iff_TRel_preserve:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_pred Pred"
  shows "rel_preserves_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_preserves_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
proof
  assume presS: "rel_preserves_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  show "rel_preserves_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  proof clarify
    fix SP SQ
    assume "Pred (TargetTerm (SP))"
    with encP have "Pred (SourceTerm SP)"
      by simp
    moreover assume "(SP, SQ)  TRel"
    with fullAbs have "(SP, SQ)  SRel"
      by simp
    ultimately have "Pred (SourceTerm SQ)"
        using presS
      by blast
    with encP show "Pred (TargetTerm (SQ))"
      by simp
  qed
next
  assume presT:
    "rel_preserves_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  show "rel_preserves_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  proof clarify
    fix SP SQ
    assume "Pred (SourceTerm SP)"
    with encP have "Pred (TargetTerm (SP))"
      by simp
    moreover assume "(SP, SQ)  SRel"
    with fullAbs have "(SP, SQ)  TRel"
      by simp
    ultimately have "Pred (TargetTerm (SQ))"
        using presT
      by blast
    with encP show "Pred (SourceTerm SQ)"
      by simp
  qed
qed

lemma (in encoding) full_abstraction_and_enc_respects_binary_pred_impl_SRel_iff_TRel_preserve:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  'b  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_binary_pred Pred"
  shows "rel_preserves_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_preserves_binary_pred
             {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
proof
  assume presS:
    "rel_preserves_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  show "rel_preserves_binary_pred
        {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  proof clarify
    fix x SP SQ
    assume "Pred (TargetTerm (SP)) x"
    with encP have "Pred (SourceTerm SP) x"
      by simp
    moreover assume "(SP, SQ)  TRel"
    with fullAbs have "(SP, SQ)  SRel"
      by simp
    ultimately have "Pred (SourceTerm SQ) x"
        using presS
      by blast
    with encP show "Pred (TargetTerm (SQ)) x"
      by simp
  qed
next
  assume presT:
    "rel_preserves_binary_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  show "rel_preserves_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  proof clarify
    fix x SP SQ
    assume "Pred (SourceTerm SP) x"
    with encP have "Pred (TargetTerm (SP)) x"
      by simp
    moreover assume "(SP, SQ)  SRel"
    with fullAbs have "(SP, SQ)  TRel"
      by simp
    ultimately have "Pred (TargetTerm (SQ)) x"
        using presT
      by blast
    with encP show "Pred (SourceTerm SQ) x"
      by simp
  qed
qed

lemma (in encoding) full_abstraction_and_enc_respects_pred_impl_SRel_iff_TRel_reflects:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_pred Pred"
  shows "rel_reflects_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_reflects_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
proof
  assume reflS: "rel_reflects_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  show "rel_reflects_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  proof clarify
    fix SP SQ
    assume "Pred (TargetTerm (SQ))"
    with encP have "Pred (SourceTerm SQ)"
      by simp
    moreover assume "(SP, SQ)  TRel"
    with fullAbs have "(SP, SQ)  SRel"
      by simp
    ultimately have "Pred (SourceTerm SP)"
        using reflS
      by blast
    with encP show "Pred (TargetTerm (SP))"
      by simp
  qed
next
  assume reflT:
    "rel_reflects_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  show "rel_reflects_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  proof clarify
    fix SP SQ
    assume "Pred (SourceTerm SQ)"
    with encP have "Pred (TargetTerm (SQ))"
      by simp
    moreover assume "(SP, SQ)  SRel"
    with fullAbs have "(SP, SQ)  TRel"
      by simp
    ultimately have "Pred (TargetTerm (SP))"
        using reflT
      by blast
    with encP show "Pred (SourceTerm SP)"
      by simp
  qed
qed

lemma (in encoding) full_abstraction_and_enc_respects_binary_pred_impl_SRel_iff_TRel_reflects:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  'b  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_binary_pred Pred"
  shows "rel_reflects_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_reflects_binary_pred
             {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
proof
  assume reflS:
    "rel_reflects_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  show "rel_reflects_binary_pred
        {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  proof clarify
    fix x SP SQ
    assume "Pred (TargetTerm (SQ)) x"
    with encP have "Pred (SourceTerm SQ) x"
      by simp
    moreover assume "(SP, SQ)  TRel"
    with fullAbs have "(SP, SQ)  SRel"
      by simp
    ultimately have "Pred (SourceTerm SP) x"
        using reflS
      by blast
    with encP show "Pred (TargetTerm (SP)) x"
      by simp
  qed
next
  assume reflT:
    "rel_reflects_binary_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
  show "rel_reflects_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred"
  proof clarify
    fix x SP SQ
    assume "Pred (SourceTerm SQ) x"
    with encP have "Pred (TargetTerm (SQ)) x"
      by simp
    moreover assume "(SP, SQ)  SRel"
    with fullAbs have "(SP, SQ)  TRel"
      by simp
    ultimately have "Pred (TargetTerm (SP)) x"
        using reflT
      by blast
    with encP show "Pred (SourceTerm SP) x"
      by simp
  qed
qed

lemma (in encoding) full_abstraction_and_enc_respects_pred_impl_SRel_iff_TRel_respects:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_pred Pred"
  shows "rel_respects_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_respects_pred {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
      using assms full_abstraction_and_enc_respects_pred_impl_SRel_iff_TRel_preserve[where
                    SRel="SRel" and TRel="TRel" and Pred="Pred"]
            full_abstraction_and_enc_respects_pred_impl_SRel_iff_TRel_reflects[where
              SRel="SRel" and TRel="TRel" and Pred="Pred"]
    by auto

lemma (in encoding) full_abstraction_and_enc_respects_binary_pred_impl_SRel_iff_TRel_respects:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Pred :: "('procS, 'procT) Proc  'b  bool"
  assumes fullAbs: "fully_abstract SRel TRel"
      and encP:    "enc_respects_binary_pred Pred"
  shows "rel_respects_binary_pred {(P, Q). SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel} Pred
          rel_respects_binary_pred
             {(P, Q). SP SQ. SP ∈T P  SQ ∈T Q  (SP, SQ)  TRel} Pred"
      using assms full_abstraction_and_enc_respects_binary_pred_impl_SRel_iff_TRel_preserve[where
                    SRel="SRel" and TRel="TRel" and Pred="Pred"]
            full_abstraction_and_enc_respects_binary_pred_impl_SRel_iff_TRel_reflects[where
              SRel="SRel" and TRel="TRel" and Pred="Pred"]
    by auto

subsection ‹Full Abstraction w.r.t. Preorders›

text ‹If there however exists a trans relation Rel that relates source terms and their
        literal translations in both directions, then the encoding is fully abstract with respect
        to the reduction of Rel to source terms and the reduction of Rel to target terms.›

lemma (in encoding) trans_source_target_relation_impl_full_abstraction:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes enc:   "S. (SourceTerm S, TargetTerm (S))  Rel
                   (TargetTerm (S), SourceTerm S)  Rel"
      and trans: "trans Rel"
  shows "fully_abstract {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
proof auto
  fix S1 S2
  assume "(SourceTerm S1, SourceTerm S2)  Rel"
  with enc trans show "(TargetTerm (S1), TargetTerm (S2))  Rel"
      unfolding trans_def
    by blast
next
  fix S1 S2
  assume "(TargetTerm (S1), TargetTerm (S2))  Rel"
  with enc trans show "(SourceTerm S1, SourceTerm S2)  Rel"
      unfolding trans_def
    by blast
qed

lemma (in encoding) source_target_relation_impl_full_abstraction_wrt_trans_closures:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes enc: "S. (SourceTerm S, TargetTerm (S))  Rel
                 (TargetTerm (S), SourceTerm S)  Rel"
  shows "fully_abstract {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel+}
          {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel+}"
proof auto
  fix S1 S2
  from enc have "(TargetTerm (S1), SourceTerm S1)  Rel+"
    by blast
  moreover assume "(SourceTerm S1, SourceTerm S2)  Rel+"
  ultimately have "(TargetTerm (S1), SourceTerm S2)  Rel+"
    by simp
  moreover from enc have "(SourceTerm S2, TargetTerm (S2))  Rel+"
    by blast
  ultimately show "(TargetTerm (S1), TargetTerm (S2))  Rel+"
    by simp
next
  fix S1 S2
  from enc have "(SourceTerm S1, TargetTerm (S1))  Rel+"
    by blast
  moreover assume "(TargetTerm (S1), TargetTerm (S2))  Rel+"
  ultimately have "(SourceTerm S1, TargetTerm (S2))  Rel+"
    by simp
  moreover from enc have "(TargetTerm (S2), SourceTerm S2)  Rel+"
    by blast
  ultimately show "(SourceTerm S1, SourceTerm S2)  Rel+"
    by simp
qed

lemma (in encoding) quasi_trans_source_target_relation_impl_full_abstraction:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes enc:   "S. (SourceTerm S, TargetTerm (S))  Rel
                   (TargetTerm (S), SourceTerm S)  Rel"
      and srel:  "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and trel:  "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      and trans: "P Q R. (P, Q)  Rel  (Q, R)  Rel  ((P  ProcS  Q  ProcT)
                   (P  ProcT  Q  ProcS))  (P, R)  Rel"
  shows "fully_abstract SRel TRel"
proof auto
  fix S1 S2
  from enc have "(TargetTerm (S1), SourceTerm S1)  Rel"
    by simp
  moreover assume "(S1, S2)  SRel"
  with srel have "(SourceTerm S1, SourceTerm S2)  Rel"
    by simp
  ultimately have "(TargetTerm (S1), SourceTerm S2)  Rel"
      using trans
    by blast
  moreover from enc have "(SourceTerm S2, TargetTerm (S2))  Rel"
    by simp
  ultimately have "(TargetTerm (S1), TargetTerm (S2))  Rel"
      using trans
    by blast
  with trel show "(S1, S2)  TRel"
    by simp
next
  fix S1 S2
  from enc have "(SourceTerm S1, TargetTerm (S1))  Rel"
    by simp
  moreover assume "(S1, S2)  TRel"
  with trel have "(TargetTerm (S1), TargetTerm (S2))  Rel"
    by simp
  ultimately have "(SourceTerm S1, TargetTerm (S2))  Rel"
      using trans
    by blast
  moreover from enc have "(TargetTerm (S2), SourceTerm S2)  Rel"
    by simp
  ultimately have "(SourceTerm S1, SourceTerm S2)  Rel"
      using trans
    by blast
  with srel show "(S1, S2)  SRel"
    by simp
qed

text ‹If an encoding is fully abstract w.r.t. SRel and TRel, then we can conclude from a pair in
        indRelRTPO or indRelSTEQ on a pair in TRel and SRel.›

lemma (in encoding) full_abstraction_impl_indRelRSTPO_to_SRel_and_TRel:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes fullAbs: "fully_abstract SRel TRel"
      and rel:     "P ≲⟦⋅⟧R<SRel,TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  TRel+"
    and "SP TQ. SP ∈S P  TQ ∈T Q  (SP, TQ)  TRel*"
proof -
  have fullAbsT: "S1 S2. (S1, S2)  SRel+  (S1, S2)  TRel+"
  proof clarify
    fix S1 S2
    assume "(S1, S2)  SRel+"
    thus "(S1, S2)  TRel+"
    proof induct
      fix S2
      assume "(S1, S2)  SRel"
      with fullAbs show "(S1, S2)  TRel+"
        by simp
    next
      case (step S2 S3)
      assume "(S1, S2)  TRel+"
      moreover assume "(S2, S3)  SRel"
      with fullAbs have "(S2, S3)  TRel+"
        by simp
      ultimately show "(S1, S3)  TRel+"
        by simp
    qed
  qed
  with rel show "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  TRel+"
      using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
    by simp
  show "SP TQ. SP ∈S P  TQ ∈T Q  (SP, TQ)  TRel*"
  proof clarify
    fix SP TQ
    assume "SP ∈S P" and "TQ ∈T Q"
    with rel obtain S where A1: "(SP, S)  SRel*"
                        and A2: "(S, TQ)  TRel*"
        using indRelRSTPO_to_SRel_and_TRel(2)[where SRel="SRel" and TRel="TRel"]
      by blast
    from A1 have "SP = S  (SP, S)  SRel+"
        using rtrancl_eq_or_trancl[of SP S SRel]
      by blast
    with fullAbsT have "(SP, S)  TRel*"
      by fast
    from this A2 show "(SP, TQ)  TRel*"
      by simp
  qed
qed

lemma (in encoding) full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and P Q  :: "('procS, 'procT) Proc"
  assumes fA:     "fully_abstract SRel TRel"
      and transT: "trans TRel"
      and reflS:  "refl SRel"
      and rel:    "P ∼⟦⋅⟧<SRel,TRel> Q"
  shows "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel"
    and "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  TRel"
    and "SP TQ. SP ∈S P  TQ ∈T Q  (SP, TQ)  TRel"
    and "TP SQ. TP ∈T P  SQ ∈S Q  (TP, SQ)  TRel"
    and "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel"
      using rel
proof induct
  case (encR S)
  show "SP SQ. SP ∈S SourceTerm S  SQ ∈S TargetTerm (S)  (SP, SQ)  SRel"
   and "SP SQ. SP ∈S SourceTerm S  SQ ∈S TargetTerm (S)  (SP, SQ)  TRel"
   and "TP SQ. TP ∈T SourceTerm S  SQ ∈S TargetTerm (S)  (TP, SQ)  TRel"
   and "TP TQ. TP ∈T SourceTerm S  TQ ∈T TargetTerm (S)  (TP, TQ)  TRel"
    by simp+
  from reflS fA show "SP TQ. SP ∈S SourceTerm S  TQ ∈T TargetTerm (S)  (SP, TQ)  TRel"
      unfolding refl_on_def
    by simp
next
  case (encL S)
  show "SP SQ. SP ∈S TargetTerm (S)  SQ ∈S SourceTerm S  (SP, SQ)  SRel"
   and "SP SQ. SP ∈S TargetTerm (S)  SQ ∈S SourceTerm S  (SP, SQ)  TRel"
   and "SP TQ. SP ∈S TargetTerm (S)  TQ ∈T SourceTerm S  (SP, TQ)  TRel"
   and "TP TQ. TP ∈T TargetTerm (S)  TQ ∈T SourceTerm S  (TP, TQ)  TRel"
    by simp+
  with reflS fA show "TP SQ. TP ∈T TargetTerm (S)  SQ ∈S SourceTerm S  (TP, SQ)  TRel"
      unfolding refl_on_def
    by simp
next
  case (source S1 S2)
  show "SP TQ. SP ∈S SourceTerm S1  TQ ∈T SourceTerm S2  (SP, TQ)  TRel"
   and "TP SQ. TP ∈T SourceTerm S1  SQ ∈S SourceTerm S2  (TP, SQ)  TRel"
   and "TP TQ. TP ∈T SourceTerm S1  TQ ∈T SourceTerm S2  (TP, TQ)  TRel"
    by simp+
  assume "(S1, S2)  SRel"
  thus "SP SQ. SP ∈S SourceTerm S1  SQ ∈S SourceTerm S2  (SP, SQ)  SRel"
    by simp
  with fA show "SP SQ. SP ∈S SourceTerm S1  SQ ∈S SourceTerm S2  (SP, SQ)  TRel"
    by simp
next
  case (target T1 T2)
  show "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  (SP, SQ)  SRel"
   and "SP SQ. SP ∈S TargetTerm T1  SQ ∈S TargetTerm T2  (SP, SQ)  TRel"
   and "SP TQ. SP ∈S TargetTerm T1  TQ ∈T TargetTerm T2  (SP, TQ)  TRel"
   and "TP SQ. TP ∈T TargetTerm T1  SQ ∈S TargetTerm T2  (TP, SQ)  TRel"
    by simp+
  assume "(T1, T2)  TRel"
  thus "TP TQ. TP ∈T TargetTerm T1  TQ ∈T TargetTerm T2  (TP, TQ)  TRel"
    by simp
next
  case (trans P Q R)
  assume A1: "SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  TRel"
     and A2: "SP TQ. SP ∈S P  TQ ∈T Q  (SP, TQ)  TRel"
     and A3: "TP SQ. TP ∈T P  SQ ∈S Q  (TP, SQ)  TRel"
     and A4: "TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel"
     and A5: "SQ SR. SQ ∈S Q  SR ∈S R  (SQ, SR)  TRel"
     and A6: "SQ TR. SQ ∈S Q  TR ∈T R  (SQ, TR)  TRel"
     and A7: "TQ SR. TQ ∈T Q  SR ∈S R  (TQ, SR)  TRel"
     and A8: "TQ TR. TQ ∈T Q  TR ∈T R  (TQ, TR)  TRel"
  show "SP SR. SP ∈S P  SR ∈S R  (SP, SR)  TRel"
  proof clarify
    fix SP SR
    assume A9: "SP ∈S P" and A10: "SR ∈S R"
    show "(SP, SR)  TRel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A1 A9 have "(SP, SQ)  TRel"
        by blast
      moreover from A5 A10 A11 have "(SQ, SR)  TRel"
        by blast
      ultimately show "(SP, SR)  TRel"
          using transT
          unfolding trans_def
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A2 A9 have "(SP, TQ)  TRel"
        by blast
      moreover from A7 A10 A11 have "(TQ, SR)  TRel"
        by blast
      ultimately show "(SP, SR)  TRel"
          using transT
          unfolding trans_def
        by blast
    qed
  qed
  with fA show "SP SR. SP ∈S P  SR ∈S R  (SP, SR)  SRel"
    by simp
  show "SP TR. SP ∈S P  TR ∈T R  (SP, TR)  TRel"
  proof clarify
    fix SP TR
    assume A9: "SP ∈S P" and A10: "TR ∈T R"
    show "(SP, TR)  TRel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A1 A9 have "(SP, SQ)  TRel"
        by blast
      moreover from A6 A10 A11 have "(SQ, TR)  TRel"
        by blast
      ultimately show "(SP, TR)  TRel"
          using transT
          unfolding trans_def
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A2 A9 have "(SP, TQ)  TRel"
        by blast
      moreover from A8 A10 A11 have "(TQ, TR)  TRel"
        by blast
      ultimately show "(SP, TR)  TRel"
          using transT
          unfolding trans_def
        by blast
    qed
  qed
  show "TP SR. TP ∈T P  SR ∈S R  (TP, SR)  TRel"
  proof clarify
    fix TP SR
    assume A9: "TP ∈T P" and A10: "SR ∈S R"
    show "(TP, SR)  TRel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A3 A9 have "(TP, SQ)  TRel"
        by blast
      moreover from A5 A10 A11 have "(SQ, SR)  TRel"
        by blast
      ultimately show "(TP, SR)  TRel"
          using transT
          unfolding trans_def
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A4 A9 have "(TP, TQ)  TRel"
        by blast
      moreover from A7 A10 A11 have "(TQ, SR)  TRel"
        by blast
      ultimately show "(TP, SR)  TRel"
          using transT
          unfolding trans_def
        by blast
    qed
  qed
  show "TP TR. TP ∈T P  TR ∈T R  (TP, TR)  TRel"
  proof clarify
    fix TP TR
    assume A9: "TP ∈T P" and A10: "TR ∈T R"
    show "(TP, TR)  TRel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A11: "SQ ∈S Q"
      with A3 A9 have "(TP, SQ)  TRel"
        by blast
      moreover from A6 A10 A11 have "(SQ, TR)  TRel"
        by blast
      ultimately show "(TP, TR)  TRel"
          using transT
          unfolding trans_def
        by blast
    next
      case (TargetTerm TQ)
      assume A11: "TQ ∈T Q"
      with A4 A9 have "(TP, TQ)  TRel"
        by blast
      moreover from A8 A10 A11 have "(TQ, TR)  TRel"
        by blast
      ultimately show "(TP, TR)  TRel"
          using transT
          unfolding trans_def
        by blast
    qed
  qed
qed

text ‹If an encoding is fully abstract w.r.t. a preorder SRel on the source and a trans
        relation TRel on the target, then there exists a trans relation, namely indRelSTEQ,
        that relates source terms and their literal translations in both direction such that its
        reductions to source terms is SRel and its reduction to target terms is TRel.›

lemma (in encoding) full_abstraction_wrt_preorders_impl_trans_source_target_relation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and reflS:   "refl SRel"
      and transT:  "trans TRel"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
                      (TargetTerm (S), SourceTerm S)  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans Rel"
proof -
  have "S. SourceTerm S ∼⟦⋅⟧<SRel,TRel> TargetTerm (S)
         TargetTerm (S) ∼⟦⋅⟧<SRel,TRel> SourceTerm S"
      using indRelSTEQ.encR[where SRel="SRel" and TRel="TRel"]
            indRelSTEQ.encL[where SRel="SRel" and TRel="TRel"]
    by blast
  moreover have "SRel = {(S1, S2). SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2}"
  proof auto
    fix S1 S2
    assume "(S1, S2)  SRel"
    thus "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
      by (rule indRelSTEQ.source[where SRel="SRel" and TRel="TRel"])
  next
    fix S1 S2
    assume "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
    with fullAbs reflS transT show "(S1, S2)  SRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(1)[where SRel="SRel"
                and TRel="TRel"]
      by blast
  qed
  moreover have "TRel =  {(T1, T2). TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2}"
  proof auto
    fix T1 T2
    assume "(T1, T2)  TRel"
    thus "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
      by (rule indRelSTEQ.target[where SRel="SRel" and TRel="TRel"])
  next
    fix T1 T2
    assume "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
    with fullAbs reflS transT show "(T1, T2)  TRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(5)[where SRel="SRel"
                and TRel="TRel"]
      by blast
  qed
  moreover have "trans (indRelSTEQ SRel TRel)"
      using indRelSTEQ.trans[where SRel="SRel" and TRel="TRel"]
      unfolding trans_def
    by blast
  ultimately show ?thesis
    by blast
qed

text ‹Thus an encoding is fully abstract w.r.t. a preorder SRel on the source and a trans
        relation TRel on the target iff there exists a trans relation that relates source
        terms and their literal translations in both directions and whose reduction to
        source/target terms is SRel/TRel.›

theorem (in encoding) fully_abstract_wrt_preorders_iff_source_target_relation_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "(fully_abstract SRel TRel  refl SRel  trans TRel) =
         (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
                       (TargetTerm (S), SourceTerm S)  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans Rel)"
proof (rule iffI)
  assume "fully_abstract SRel TRel  refl SRel  trans TRel"
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans Rel"
      using full_abstraction_wrt_preorders_impl_trans_source_target_relation[where SRel="SRel"
              and TRel="TRel"]
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel
                  (TargetTerm (S), SourceTerm S)  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans Rel"
  from this obtain Rel
    where A1: "S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel"
      and A2: "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and A3: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}" and A4: "trans Rel"
    by blast
  hence "fully_abstract SRel TRel"
      using trans_source_target_relation_impl_full_abstraction[where Rel="Rel"]
    by blast
  moreover have "refl SRel"
    unfolding refl_on_def
  proof auto
    fix S
    from A1 have "(SourceTerm S, TargetTerm (S))  Rel"
      by blast
    moreover from A1 have "(TargetTerm (S), SourceTerm S)  Rel"
      by blast
    ultimately have "(SourceTerm S, SourceTerm S)  Rel"
        using A4
        unfolding trans_def
      by blast
    with A2 show "(S, S)  SRel"
      by blast
  qed
  moreover from A3 A4 have "trans TRel"
      unfolding trans_def
    by blast
  ultimately show "fully_abstract SRel TRel  refl SRel  trans TRel"
    by blast
qed

subsection ‹Full Abstraction w.r.t. Equivalences›

text ‹If there exists a relation Rel that relates source terms and their literal translations
        and whose sym closure is trans, then the encoding is fully abstract with respect
        to the reduction of the sym closure of Rel to source/target terms.›

lemma (in encoding) source_target_relation_with_trans_symcl_impl_full_abstraction:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes enc:   "S. (SourceTerm S, TargetTerm (S))  Rel"
      and trans: "trans (symcl Rel)"
  shows "fully_abstract {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
          {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}"
proof auto
  fix S1 S2
  from enc have "(TargetTerm (S1), SourceTerm S1)  symcl Rel"
    by (simp add: symcl_def)
  moreover assume "(SourceTerm S1, SourceTerm S2)  symcl Rel"
  moreover from enc have "(SourceTerm S2, TargetTerm (S2))  symcl Rel"
    by (simp add: symcl_def)
  ultimately show "(TargetTerm (S1), TargetTerm (S2))  symcl Rel"
      using trans
      unfolding trans_def
    by blast
next
  fix S1 S2
  from enc have "(SourceTerm S1, TargetTerm (S1))  symcl Rel"
    by (simp add: symcl_def)
  moreover assume "(TargetTerm (S1), TargetTerm (S2))  symcl Rel"
  moreover from enc have "(TargetTerm (S2), SourceTerm S2)  symcl Rel"
    by (simp add: symcl_def)
  ultimately show "(SourceTerm S1, SourceTerm S2)  symcl Rel"
      using trans
      unfolding trans_def
    by blast
qed

text ‹If an encoding is fully abstract w.r.t. the equivalences SRel and TRel, then there exists a
        preorder, namely indRelRSTPO, that relates source terms and their literal translations such
        that its reductions to source terms is SRel and its reduction to target terms is TRel.›

lemma (in encoding) fully_abstract_wrt_equivalences_impl_symcl_source_target_relation_is_preorder:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and reflT:   "refl TRel"
      and symmT:   "sym TRel"
      and transT:  "trans TRel"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
proof -
  from fullAbs reflT have reflS: "refl SRel"
      unfolding refl_on_def
    by auto
  from fullAbs symmT have symmS: "sym SRel"
      unfolding sym_def
    by auto
  from fullAbs transT have transS: "trans SRel"
      unfolding trans_def
    by blast
  have "S. SourceTerm S ≲⟦⋅⟧R<SRel,TRel> TargetTerm (S)"
      using indRelRSTPO.encR[where SRel="SRel" and TRel="TRel"]
    by blast
  moreover
  have "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl (indRelRSTPO SRel TRel)}"
  proof auto
    fix S1 S2
    assume "(S1, S2)  SRel"
    thus "(SourceTerm S1, SourceTerm S2)  symcl (indRelRSTPO SRel TRel)"
      by (simp add: symcl_def indRelRSTPO.source[where SRel="SRel" and TRel="TRel"])
  next
    fix S1 S2
    assume "(SourceTerm S1, SourceTerm S2)  symcl (indRelRSTPO SRel TRel)"
    moreover from transS
    have "SourceTerm S1 ≲⟦⋅⟧R<SRel,TRel> SourceTerm S2  (S1, S2)  SRel"
        using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
              trancl_id[of SRel]
      by blast
    moreover from symmS transS
    have "SourceTerm S2 ≲⟦⋅⟧R<SRel,TRel> SourceTerm S1  (S1, S2)  SRel"
        using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
              trancl_id[of SRel]
        unfolding sym_def
      by blast
    ultimately show "(S1, S2)  SRel"
      by (auto simp add: symcl_def)
  qed
  moreover
  have "TRel =  {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl (indRelRSTPO SRel TRel)}"
  proof auto
    fix T1 T2
    assume "(T1, T2)  TRel"
    thus "(TargetTerm T1, TargetTerm T2)  symcl (indRelRSTPO SRel TRel)"
      by (simp add: symcl_def indRelRSTPO.target[where SRel="SRel" and TRel="TRel"])
  next
    fix T1 T2
    assume "(TargetTerm T1, TargetTerm T2)  symcl (indRelRSTPO SRel TRel)"
    moreover from transT
    have "TargetTerm T1 ≲⟦⋅⟧R<SRel,TRel> TargetTerm T2  (T1, T2)  TRel"
        using indRelRSTPO_to_SRel_and_TRel(4)[where SRel="SRel" and TRel="TRel"]
              trancl_id[of TRel]
      by blast
    moreover from symmT transT
    have "TargetTerm T2 ≲⟦⋅⟧R<SRel,TRel> TargetTerm T1  (T1, T2)  TRel"
        using indRelRSTPO_to_SRel_and_TRel(4)[where SRel="SRel" and TRel="TRel"]
              trancl_id[of TRel]
        unfolding sym_def
      by blast
    ultimately show "(T1, T2)  TRel"
      by (auto simp add: symcl_def)
  qed
  moreover have "refl (symcl (indRelRSTPO SRel TRel))"
    unfolding refl_on_def
  proof auto
    fix P
    show "(P, P)  symcl (indRelRSTPO SRel TRel)"
    proof (cases P)
      case (SourceTerm SP)
      assume "SP ∈S P"
      with reflS show "(P, P)  symcl (indRelRSTPO SRel TRel)"
          unfolding refl_on_def
        by (simp add: symcl_def indRelRSTPO.source)
    next
      case (TargetTerm TP)
      assume "TP ∈T P"
      with reflT show "(P, P)  symcl (indRelRSTPO SRel TRel)"
          unfolding refl_on_def
        by (simp add: symcl_def indRelRSTPO.target)
    qed
  qed
  moreover have "trans (symcl (indRelRSTPO SRel TRel))"
  proof -
    have "P Q R. P ≲⟦⋅⟧R<SRel,TRel> Q  R ≲⟦⋅⟧R<SRel,TRel> Q  (P, R)  (indRelRSTPO SRel TRel)
           Q ≲⟦⋅⟧R<SRel,TRel> P  Q ≲⟦⋅⟧R<SRel,TRel> R"
    proof clarify
      fix P Q R
      assume A1: "P ≲⟦⋅⟧R<SRel,TRel> Q" and A2: "R ≲⟦⋅⟧R<SRel,TRel> Q"
         and A3: "(P, R)  (indRelRSTPO SRel TRel)" and A4: "(Q, R)  (indRelRSTPO SRel TRel)"
      show "Q ≲⟦⋅⟧R<SRel,TRel> P"
      proof (cases P)
        case (SourceTerm SP)
        assume A5: "SP ∈S P"
        show "Q ≲⟦⋅⟧R<SRel,TRel> P"
        proof (cases Q)
          case (SourceTerm SQ)
          assume A6: "SQ ∈S Q"
          with transS A1 A5 have "(SP, SQ)  SRel"
              using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
                    trancl_id[of SRel]
            by blast
          with symmS A5 A6 show "Q ≲⟦⋅⟧R<SRel,TRel> P"
              unfolding sym_def
            by (simp add: indRelRSTPO.source)
        next
          case (TargetTerm TQ)
          assume A6: "TQ ∈T Q"
          show "Q ≲⟦⋅⟧R<SRel,TRel> P"
          proof (cases R)
            case (SourceTerm SR)
            assume A7: "SR ∈S R"
            with fullAbs A2 A6 have "(SR, TQ)  TRel*"
                using full_abstraction_impl_indRelRSTPO_to_SRel_and_TRel(2)[where SRel="SRel"
                       and TRel="TRel"] trancl_id[of "TRel="] reflcl_of_refl_rel[of TRel]
                      trancl_reflcl[of TRel]
                unfolding trans_def
              by blast
            with transT reflT have "(SR, TQ)  TRel"
                using trancl_id[of "TRel="] reflcl_of_refl_rel[of TRel] trancl_reflcl[of TRel]
              by auto
            with symmT have "(TQ, SR)  TRel"
                unfolding sym_def
              by simp
            moreover from fullAbs A1 A5 A6 have "(SP, TQ)  TRel*"
                using full_abstraction_impl_indRelRSTPO_to_SRel_and_TRel(2)[where SRel="SRel"
                       and TRel="TRel"]
                unfolding trans_def
              by blast
            with transT reflT have "(SP, TQ)  TRel"
                using trancl_id[of "TRel="] reflcl_of_refl_rel[of TRel] trancl_reflcl[of TRel]
              by auto
            ultimately have "(SP, SR)  TRel"
                using transT
                unfolding trans_def
              by blast
            with fullAbs have "(SP, SR)  SRel"
              by simp
            with A3 A5 A7 show ?thesis
              by (simp add: indRelRSTPO.source)
          next
            case (TargetTerm TR)
            assume A7: "TR ∈T R"
            with transT A2 A6 have "(TR, TQ)  TRel"
                using indRelRSTPO_to_SRel_and_TRel(4)[where SRel="SRel" and TRel="TRel"]
                      trancl_id[of "TRel"]
              by blast
            with symmT have "(TQ, TR)  TRel"
                unfolding sym_def
              by simp
            with A4 A6 A7 show ?thesis
              by (simp add: indRelRSTPO.target)
          qed
        qed
      next
        case (TargetTerm TP)
        assume A5: "TP ∈T P"
        show "Q ≲⟦⋅⟧R<SRel,TRel> P"
        proof (cases Q)
          case (SourceTerm SQ)
          assume "SQ ∈S Q"
          with A1 A5 show ?thesis
              using indRelRSTPO_to_SRel_and_TRel(3)[where SRel="SRel" and TRel="TRel"]
            by blast
        next
          case (TargetTerm TQ)
          assume A6: "TQ ∈T Q"
          with transT A1 A5 have "(TP, TQ)  TRel"
              using indRelRSTPO_to_SRel_and_TRel(4)[where SRel="SRel" and TRel="TRel"]
                    trancl_id[of "TRel"]
            by blast
          with symmT have "(TQ, TP)  TRel"
              unfolding sym_def
            by simp
          with A5 A6 show "Q ≲⟦⋅⟧R<SRel,TRel> P"
            by (simp add: indRelRSTPO.target)
        qed
      qed
    qed
    moreover
    have "P Q R. P ≲⟦⋅⟧R<SRel,TRel> Q  P ≲⟦⋅⟧R<SRel,TRel> R  (Q, R)  (indRelRSTPO SRel TRel)
           Q ≲⟦⋅⟧R<SRel,TRel> P  R ≲⟦⋅⟧R<SRel,TRel> P"
    proof clarify
      fix P Q R
      assume A1: "P ≲⟦⋅⟧R<SRel,TRel> Q" and A2: "P ≲⟦⋅⟧R<SRel,TRel> R"
         and A3: "(Q, R)  (indRelRSTPO SRel TRel)" and A4: "(R, P)  (indRelRSTPO SRel TRel)"
      show "Q ≲⟦⋅⟧R<SRel,TRel> P"
      proof (cases P)
        case (SourceTerm SP)
        assume A5: "SP ∈S P"
        show "Q ≲⟦⋅⟧R<SRel,TRel> P"
        proof (cases Q)
          case (SourceTerm SQ)
          assume A6: "SQ ∈S Q"
          with transS A1 A5 have "(SP, SQ)  SRel"
              using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
                    trancl_id[of "SRel"]
            by blast
          with symmS A5 A6 show "Q ≲⟦⋅⟧R<SRel,TRel> P"
              unfolding sym_def
            by (simp add: indRelRSTPO.source)
        next
          case (TargetTerm TQ)
          assume A6: "TQ ∈T Q"
          show "Q ≲⟦⋅⟧R<SRel,TRel> P"
          proof (cases R)
            case (SourceTerm SR)
            assume A7: "SR ∈S R"
            with transS A2 A5 have "(SP, SR)  SRel"
                using indRelRSTPO_to_SRel_and_TRel(1)[where SRel="SRel" and TRel="TRel"]
                      trancl_id[of "SRel"]
              by blast
            with symmS have "(SR, SP)  SRel"
                unfolding sym_def
              by simp
            with A4 A5 A7 show ?thesis
              by (simp add: indRelRSTPO.source)
          next
            case (TargetTerm TR)
            from fullAbs A1 A5 A6 have "(SP, TQ)  TRel*"
                using full_abstraction_impl_indRelRSTPO_to_SRel_and_TRel(2)[where SRel="SRel" and
                       TRel="TRel"]
                unfolding trans_def
              by blast
            with transT reflT have "(SP, TQ)  TRel"
                using trancl_id[of "TRel="] reflcl_of_refl_rel[of TRel] trancl_reflcl[of TRel]
              by auto
            with symmT have "(TQ, SP)  TRel"
                unfolding sym_def
              by simp
            moreover assume A7: "TR ∈T R"
            with fullAbs A2 A5 have "(SP, TR)  TRel*"
                using full_abstraction_impl_indRelRSTPO_to_SRel_and_TRel(2)[where SRel="SRel" and
                        TRel="TRel"]
                unfolding trans_def
              by blast
            with transT reflT have "(SP, TR)  TRel"
                using trancl_id[of "TRel="] reflcl_of_refl_rel[of TRel] trancl_reflcl[of TRel]
              by auto
            ultimately have "(TQ, TR)  TRel"
                using transT
                unfolding trans_def
              by blast
            with A3 A6 A7 show ?thesis
              by (simp add: indRelRSTPO.target)
          qed
        qed
      next
        case (TargetTerm TP)
        assume A5: "TP ∈T P"
        show "Q ≲⟦⋅⟧R<SRel,TRel> P"
        proof (cases Q)
          case (SourceTerm SQ)
          assume "SQ ∈S Q"
          with A1 A5 show ?thesis
              using indRelRSTPO_to_SRel_and_TRel(3)[where SRel="SRel" and TRel="TRel"]
            by blast
        next
          case (TargetTerm TQ)
          assume A6: "TQ ∈T Q"
          with transT A1 A5 have "(TP, TQ)  TRel"
              using indRelRSTPO_to_SRel_and_TRel(4)[where SRel="SRel" and TRel="TRel"]
                    trancl_id[of "TRel"]
            by blast
          with symmT have "(TQ, TP)  TRel"
              unfolding sym_def
            by simp
          with A5 A6 show "Q ≲⟦⋅⟧R<SRel,TRel> P"
            by (simp add: indRelRSTPO.target)
        qed
      qed
    qed
    moreover from reflS reflT have "refl (indRelRSTPO SRel TRel)"
        using indRelRSTPO_refl[where SRel="SRel" and TRel="TRel"]
      by blast
    moreover have "trans (indRelRSTPO SRel TRel)"
        using indRelRSTPO.trans[where SRel="SRel" and TRel="TRel"]
        unfolding trans_def
      by blast
    ultimately show "trans (symcl (indRelRSTPO SRel TRel))"
        using symm_closure_of_preorder_is_trans[where Rel="indRelRSTPO SRel TRel"]
      by blast
  qed
  ultimately show ?thesis
      unfolding preorder_on_def
    by blast
qed

lemma (in encoding) fully_abstract_impl_symcl_source_target_relation_is_preorder:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract ((symcl (SRel=))+) ((symcl (TRel=))+)"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 ((symcl (SRel=))+) = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 ((symcl (TRel=))+) = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
proof -
  have "refl ((symcl (TRel=))+)"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[of TRel]
            refl_rtrancl[of TRel]
      unfolding sym_def refl_on_def
    by auto
  moreover have "sym ((symcl (TRel=))+)"
      using sym_symcl[of "TRel="] sym_trancl[of "symcl (TRel=)"]
    by simp
  moreover have "trans ((symcl (TRel=))+)"
    by simp
  ultimately show ?thesis
      using fully_abstract_wrt_equivalences_impl_symcl_source_target_relation_is_preorder[where
             SRel="(symcl (SRel=))+" and TRel="(symcl (TRel=))+"] fullAbs
            refl_symm_closure_is_symm_refl_closure
      unfolding preorder_on_def
    by blast
qed

lemma (in encoding) fully_abstract_wrt_preorders_impl_source_target_relation_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 ((refl SRel  trans TRel)
                    trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}))"
proof -
  define Rel where "Rel = (indRelSTEQ SRel TRel) - ({(P, Q). S. S ∈T P  S ∈S Q}
                  {(P, Q). S1 S2. S1 ∈S P  S2 ∈S Q  (S1, S2)  SRel}
                  {(P, Q). T1 T2. T1 ∈T P  T2 ∈T Q  (T1, T2)  TRel})"
  from Rel_def have "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelSTEQ.encR[where SRel="SRel" and TRel="TRel"])
  moreover from Rel_def have "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
  proof auto
    fix S1 S2
    assume "(S1, S2)  SRel"
    thus "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
      by (simp add: indRelSTEQ.source[where SRel="SRel" and TRel="TRel"])
  qed
  moreover from Rel_def have "TRel =  {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
  proof auto
    fix T1 T2
    assume "(T1, T2)  TRel"
    thus "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
      by (simp add: indRelSTEQ.target[where SRel="SRel" and TRel="TRel"])
  qed
  moreover
  have "(refl SRel  trans TRel)  trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  proof (rule iffI, erule conjE)
    assume reflS: "refl SRel" and transT: "trans TRel"
    have "Rel  {(P, Q). S. S ∈T P  S ∈S Q} = indRelSTEQ SRel TRel"
    proof (auto simp add: Rel_def)
      fix S
      show "TargetTerm (S) ∼⟦⋅⟧<SRel,TRel> SourceTerm S"
        by (rule indRelSTEQ.encL)
    next
      fix S1 S2
      assume "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
      with fullAbs reflS transT have "(S1, S2)  SRel"
          using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(1)[where
                SRel="SRel" and TRel="TRel"]
        by blast
      moreover assume "(S1, S2)  SRel"
      ultimately show False
        by simp
    next
      fix T1 T2
      assume "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
      with fullAbs reflS transT have "(T1, T2)  TRel"
          using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(5)[where
                SRel="SRel" and TRel="TRel"]
        by blast
      moreover assume "(T1, T2)  TRel"
      ultimately show False
        by simp
    qed
    thus "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
        using indRelSTEQ_trans[where SRel="SRel" and TRel="TRel"]
        unfolding trans_def
      by blast
  next
    assume transR: "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
    show "refl SRel  trans TRel"
      unfolding trans_def refl_on_def
    proof auto
      fix S
      from Rel_def have "(SourceTerm S, TargetTerm (S))  Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
        by (simp add: indRelSTEQ.encR)
      moreover have "(TargetTerm (S), SourceTerm S)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
        by simp
      ultimately have "(SourceTerm S, SourceTerm S)  Rel"
          using transR
          unfolding trans_def
        by blast
      with Rel_def show "(S, S)  SRel"
        by simp
    next
      fix TP TQ TR
      assume "(TP, TQ)  TRel"
      with Rel_def have "(TargetTerm TP, TargetTerm TQ)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
        by (simp add: indRelSTEQ.target)
      moreover assume "(TQ, TR)  TRel"
      with Rel_def have "(TargetTerm TQ, TargetTerm TR)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
        by (simp add: indRelSTEQ.target)
      ultimately have "(TargetTerm TP, TargetTerm TR)  Rel"
          using transR
          unfolding trans_def
        by blast
      with Rel_def show "(TP, TR)  TRel"
        by simp
    qed
  qed
  ultimately show ?thesis
    by blast
qed

lemma (in encoding) fully_abstract_wrt_preorders_impl_source_target_relation_is_trans_B:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and reflT:   "refl TRel"
      and transT:  "trans TRel"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
proof -
  define Rel where "Rel = (indRelSTEQ SRel TRel) - {(P, Q). S. S ∈T P  S ∈S Q}"
  from fullAbs reflT have reflS: "refl SRel"
      unfolding refl_on_def
    by auto
  from Rel_def have "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelSTEQ.encR[where SRel="SRel" and TRel="TRel"])
  moreover from Rel_def have "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
  proof auto
    fix S1 S2
    assume "(S1, S2)  SRel"
    thus "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
      by (simp add: indRelSTEQ.source[where SRel="SRel" and TRel="TRel"])
  next
    fix S1 S2
    assume "SourceTerm S1 ∼⟦⋅⟧<SRel,TRel> SourceTerm S2"
    with fullAbs transT reflS show "(S1, S2)  SRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(1)[where SRel="SRel"
              and TRel="TRel"]
      by blast
  qed
  moreover from Rel_def have "TRel =  {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
  proof auto
    fix T1 T2
    assume "(T1, T2)  TRel"
    thus "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
      by (simp add: indRelSTEQ.target[where SRel="SRel" and TRel="TRel"])
  next
    fix T1 T2
    assume "TargetTerm T1 ∼⟦⋅⟧<SRel,TRel> TargetTerm T2"
    with fullAbs transT reflS show "(T1, T2)  TRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(5)[where SRel="SRel"
              and TRel="TRel"]
      by blast
  qed
  moreover from Rel_def have "Rel  {(P, Q). S. S ∈T P  S ∈S Q} = indRelSTEQ SRel TRel"
    by (auto simp add: indRelSTEQ.encL)
  hence "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
      using indRelSTEQ.trans[where SRel="SRel" and TRel="TRel"]
      unfolding trans_def
    by auto
  ultimately show ?thesis
    by blast
qed

text ‹Thus an encoding is fully abstract w.r.t. an equivalence SRel on the source and an
        equivalence TRel on the target iff there exists a relation that relates source terms and
        their literal translations, whose sym closure is a preorder such that the reduction
        of this sym closure to source/target terms is SRel/TRel.›

lemma (in encoding) fully_abstract_wrt_equivalences_iff_symcl_source_target_relation_is_preorder:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "(fully_abstract SRel TRel  equivalence TRel) =
         (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel))"
proof (rule iffI)
  assume "fully_abstract SRel TRel  equivalence TRel"
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
      using fully_abstract_wrt_equivalences_impl_symcl_source_target_relation_is_preorder[where
             SRel="SRel" and TRel="TRel"]
      unfolding equiv_def
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
  from this obtain Rel
    where     "S. (SourceTerm S, TargetTerm (S))  Rel"
      and     "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}"
      and A1: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}"
      and A2: "preorder (symcl Rel)"
    by blast
  hence A5: "fully_abstract SRel TRel"
      using source_target_relation_with_trans_symcl_impl_full_abstraction[where Rel="Rel"]
      unfolding preorder_on_def
    by blast
  moreover have "equivalence TRel"
    unfolding trans_def equiv_def sym_def refl_on_def
  proof auto
    fix T
    from A1 A2 show "(T, T)  TRel"
        unfolding preorder_on_def refl_on_def
      by blast
  next
    fix T1 T2
    assume "(T1, T2)  TRel"
    with A1 show "(T2, T1)  TRel"
      by (auto simp add: symcl_def)
  next
    fix T1 T2 T3
    assume "(T1, T2)  TRel" and "(T2, T3)  TRel"
    with A1 A2 show "(T1, T3)  TRel"
        unfolding trans_def preorder_on_def
      by blast
  qed
  ultimately show "fully_abstract SRel TRel  equivalence TRel"
    by blast
qed

lemma (in encoding) fully_abstract_iff_symcl_source_target_relation_is_preorder:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "fully_abstract ((symcl (SRel=))+) ((symcl (TRel=))+) =
         (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 (symcl (SRel=))+ = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 (symcl (TRel=))+ = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel))"
proof (rule iffI)
  assume "fully_abstract ((symcl (SRel=))+) ((symcl (TRel=))+)"
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 (symcl (SRel=))+ = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 (symcl (TRel=))+ = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
      using fully_abstract_impl_symcl_source_target_relation_is_preorder[where SRel="SRel" and
             TRel="TRel"]
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 (symcl (SRel=))+ = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}
                 (symcl (TRel=))+ = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}
                 preorder (symcl Rel)"
  from this obtain Rel
    where     "S. (SourceTerm S, TargetTerm (S))  Rel"
      and     "(symcl (SRel=))+ = {(S1, S2). (SourceTerm S1, SourceTerm S2)  symcl Rel}"
      and A1: "(symcl (TRel=))+ = {(T1, T2). (TargetTerm T1, TargetTerm T2)  symcl Rel}"
      and A2: "preorder (symcl Rel)"
    by blast
  thus "fully_abstract ((symcl (SRel=))+) ((symcl (TRel=))+)"
      using source_target_relation_with_trans_symcl_impl_full_abstraction[where Rel="Rel"]
      unfolding preorder_on_def
    by blast
qed

subsection ‹Full Abstraction without Relating Translations to their Source Terms›

text ‹Let Rel be the result of removing from indRelSTEQ all pairs of two source or two target
        terms that are not contained in SRel or TRel. Then a fully abstract encoding ensures that
        Rel is trans iff SRel is refl and TRel is trans.›

lemma (in encoding) full_abstraction_impl_indRelSTEQ_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
    and Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and rel:     "Rel = ((indRelSTEQ SRel TRel)
                    - {(P, Q). (P  ProcS  Q  ProcS)  (P  ProcT  Q  ProcT)})
                     {(P, Q). (SP SQ. SP ∈S P  SQ ∈S Q  (SP, SQ)  SRel)
                         (TP TQ. TP ∈T P  TQ ∈T Q  (TP, TQ)  TRel)}"
  shows "(refl SRel  trans TRel) = trans Rel"
    unfolding trans_def
proof auto
  fix P Q R
  assume A1: "refl SRel" and A2: "x y. (x, y)  TRel  (z. (y, z)  TRel  (x, z)  TRel)"
     and A3: "(P, Q)  Rel" and A4: "(Q, R)  Rel"
  from fullAbs rel have A5: "SP SQ. (SourceTerm SP, SourceTerm SQ)  Rel  (SP, SQ)  TRel"
    by simp
  from rel have A6: "TP TQ. (TargetTerm TP, TargetTerm TQ)  Rel  (TP, TQ)  TRel"
    by simp
  have A7: "SP TQ. (SourceTerm SP, TargetTerm TQ)  Rel  (SP, TQ)  TRel"
  proof clarify
    fix SP TQ
    assume "(SourceTerm SP, TargetTerm TQ)  Rel"
    with rel have "SourceTerm SP ∼⟦⋅⟧<SRel,TRel> TargetTerm TQ"
      by simp
    with A1 A2 fullAbs show "(SP, TQ)  TRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(3)[where
              SRel="SRel" and TRel="TRel"]
        unfolding trans_def
      by blast
  qed
  have A8: "TP SQ. (TargetTerm TP, SourceTerm SQ)  Rel  (TP, SQ)  TRel"
  proof clarify
    fix TP SQ
    assume "(TargetTerm TP, SourceTerm SQ)  Rel"
    with rel have "TargetTerm TP ∼⟦⋅⟧<SRel,TRel> SourceTerm SQ"
      by simp
    with A1 A2 fullAbs show "(TP, SQ)  TRel"
        using full_abstraction_wrt_preorders_impl_indRelSTEQ_to_SRel_and_TRel(4)[where
              SRel="SRel" and TRel="TRel"]
        unfolding trans_def
      by blast
  qed
  show "(P, R)  Rel"
  proof (cases P)
    case (SourceTerm SP)
    assume A9: "SP ∈S P"
    show "(P, R)  Rel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A10: "SQ ∈S Q"
      with A3 A5 A9 have A11: "(SP, SQ)  TRel"
        by simp
      show "(P, R)  Rel"
      proof (cases R)
        case (SourceTerm SR)
        assume A12: "SR ∈S R"
        with A4 A5 A10 have "(SQ, SR)  TRel"
          by simp
        with A2 A11 have "(SP, SR)  TRel"
          by blast
        with fullAbs have "(SP, SR)  SRel"
          by simp
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      next
        case (TargetTerm TR)
        assume A12: "TR ∈T R"
        from A9 have "P ∼⟦⋅⟧<SRel,TRel> TargetTerm (SP)"
          by (simp add: indRelSTEQ.encR)
        moreover from A4 A7 A10 A12 have "(SQ, TR)  TRel"
          by simp
        with A2 A11 have "(SP, TR)  TRel"
          by blast
        with A12 have "TargetTerm (SP) ∼⟦⋅⟧<SRel,TRel> R"
          by (simp add: indRelSTEQ.target)
        ultimately have "P ∼⟦⋅⟧<SRel, TRel> R"
          by (rule indRelSTEQ.trans)
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      qed
    next
      case (TargetTerm TQ)
      assume A10: "TQ ∈T Q"
      with A3 A7 A9 have A11: "(SP, TQ)  TRel"
        by simp
      show "(P, R)  Rel"
      proof (cases R)
        case (SourceTerm SR)
        assume A12: "SR ∈S R"
        with A4 A8 A10 have "(TQ, SR)  TRel"
          by simp
        with A2 A11 have "(SP, SR)  TRel"
          by blast
        with fullAbs have "(SP, SR)  SRel"
          by simp
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      next
        case (TargetTerm TR)
        assume A12: "TR ∈T R"
        from A9 have "P ∼⟦⋅⟧<SRel,TRel> TargetTerm (SP)"
          by (simp add: indRelSTEQ.encR)
        moreover from A4 A6 A10 A12 have "(TQ, TR)  TRel"
          by simp
        with A2 A11 have "(SP, TR)  TRel"
          by blast
        with A12 have "TargetTerm (SP) ∼⟦⋅⟧<SRel,TRel> R"
          by (simp add: indRelSTEQ.target)
        ultimately have "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
        with A9 A12 rel show "(P, R)  Rel"
          by simp
      qed
    qed
  next
    case (TargetTerm TP)
    assume A9: "TP ∈T P"
    show "(P, R)  Rel"
    proof (cases Q)
      case (SourceTerm SQ)
      assume A10: "SQ ∈S Q"
      with A3 A8 A9 have A11: "(TP, SQ)  TRel"
        by simp
      show "(P, R)  Rel"
      proof (cases R)
        case (SourceTerm SR)
        assume A12: "SR ∈S R"
        with A4 A5 A10 have "(SQ, SR)  TRel"
          by simp
        with A2 A11 have "(TP, SR)  TRel"
          by blast
        with A9 have "P ∼⟦⋅⟧<SRel,TRel> TargetTerm (SR)"
          by (simp add: indRelSTEQ.target)
        moreover from A12 have "TargetTerm (SR) ∼⟦⋅⟧<SRel,TRel> R"
          by (simp add: indRelSTEQ.encL)
        ultimately have "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      next
        case (TargetTerm TR)
        assume A12: "TR ∈T R"
        with A4 A7 A10 have "(SQ, TR)  TRel"
          by simp
        with A2 A11 have "(TP, TR)  TRel"
          by blast
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      qed
    next
      case (TargetTerm TQ)
      assume A10: "TQ ∈T Q"
      with A3 A6 A9 have A11: "(TP, TQ)  TRel"
        by simp
      show "(P, R)  Rel"
      proof (cases R)
        case (SourceTerm SR)
        assume A12: "SR ∈S R"
        with A4 A8 A10 have "(TQ, SR)  TRel"
          by simp
        with A2 A11 have "(TP, SR)  TRel"
          by blast
        with A9 have "P ∼⟦⋅⟧<SRel,TRel> TargetTerm (SR)"
          by (simp add: indRelSTEQ.target)
        moreover from A12 have "TargetTerm (SR) ∼⟦⋅⟧<SRel,TRel> R"
          by (simp add: indRelSTEQ.encL)
        ultimately have "P ∼⟦⋅⟧<SRel,TRel> R"
          by (rule indRelSTEQ.trans)
        with rel A9 A12 show "(P, R)  Rel"
          by simp
      next
        case (TargetTerm TR)
        assume A12: "TR ∈T R"
        with A4 A6 A10 have "(TQ, TR)  TRel"
          by simp
        with A2 A11 have "(TP, TR)  TRel"
          by blast
        with A9 A12 rel show "(P, R)  Rel"
          by simp
      qed
    qed
  qed
next
  assume B: "x y. (x, y)  Rel  (z. (y, z)  Rel  (x, z)  Rel)"
  thus "refl SRel"
    unfolding refl_on_def
  proof auto
    fix S
    from rel have "(SourceTerm S, TargetTerm (S))  Rel"
      by (simp add: indRelSTEQ.encR)
    moreover from rel have "(TargetTerm (S), SourceTerm S)  Rel"
      by (simp add: indRelSTEQ.encL)
    ultimately have "(SourceTerm S, SourceTerm S)  Rel"
        using B
      by blast
    with rel show "(S, S)  SRel"
      by simp
  qed
next
  fix TP TQ TR
  assume "x y. (x, y)  Rel  (z. (y, z)  Rel  (x, z)  Rel)"
  moreover assume "(TP, TQ)  TRel"
  with rel have "(TargetTerm TP, TargetTerm TQ)  Rel"
    by simp
  moreover assume "(TQ, TR)  TRel"
  with rel have "(TargetTerm TQ, TargetTerm TR)  Rel"
    by simp
  ultimately have "(TargetTerm TP, TargetTerm TR)  Rel"
    by blast
  with rel show "(TP, TR)  TRel"
    by simp
qed

text ‹Whenever an encoding induces a trans relation that includes SRel and TRel and relates
        source terms to their literal translations in both directions, the encoding is fully
        abstract w.r.t. SRel and TRel.›

lemma (in encoding) trans_source_target_relation_impl_fully_abstract:
  fixes Rel  :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
    and SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes enc:   "S. (SourceTerm S, TargetTerm (S))  Rel
                   (TargetTerm (S), SourceTerm S)  Rel"
      and srel:  "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and trel:  "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      and trans: "trans Rel"
  shows "fully_abstract SRel TRel"
proof auto
  fix S1 S2
  assume "(S1, S2)  SRel"
  with srel have "(SourceTerm S1, SourceTerm S2)  Rel"
    by simp
  with enc trans have "(TargetTerm (S1), TargetTerm (S2))  Rel"
      unfolding trans_def
    by blast
  with trel show "(S1, S2)  TRel"
    by simp
next
  fix S1 S2
  assume "(S1, S2)  TRel"
  with trel have "(TargetTerm (S1), TargetTerm (S2))  Rel"
    by simp
  with enc trans have "(SourceTerm S1, SourceTerm S2)  Rel"
      unfolding trans_def
    by blast
  with srel show "(S1, S2)  SRel"
    by simp
qed

text ‹Assume TRel is a preorder. Then an encoding is fully abstract w.r.t. SRel and TRel iff
        there exists a relation that relates add least all source terms to their literal
        translations, includes SRel and TRel, and whose union with the relation that relates
        exactly all literal translations to their source terms is trans.›

lemma (in encoding) source_target_relation_with_trans_impl_full_abstraction:
  fixes Rel :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set"
  assumes enc:   "S. (SourceTerm S, TargetTerm (S))  Rel"
      and trans: "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  shows "fully_abstract {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
proof auto
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  from Rel'_def have "(TargetTerm (S1), SourceTerm S1)  Rel'"
    by simp
  moreover assume "(SourceTerm S1, SourceTerm S2)  Rel"
  with Rel'_def have "(SourceTerm S1, SourceTerm S2)  Rel'"
    by simp
  moreover from enc Rel'_def have "(SourceTerm S2, TargetTerm (S2))  Rel'"
    by simp
  ultimately show "(TargetTerm (S1), TargetTerm (S2))  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
next
  fix S1 S2
  define Rel' where "Rel' = Rel  {(P, Q). S. S ∈T P  S ∈S Q}"
  from enc Rel'_def have "(SourceTerm S1, TargetTerm (S1))  Rel'"
    by simp
  moreover assume "(TargetTerm (S1), TargetTerm (S2))  Rel"
  with Rel'_def have "(TargetTerm (S1), TargetTerm (S2))  Rel'"
    by simp
  moreover from Rel'_def have "(TargetTerm (S2), SourceTerm S2)  Rel'"
    by simp
  ultimately show "(SourceTerm S1, SourceTerm S2)  Rel"
      using trans Rel'_def
      unfolding trans_def
    by blast
qed

lemma (in encoding) fully_abstract_wrt_preorders_iff_source_target_relation_is_transB:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes preord: "preorder TRel"
  shows "fully_abstract SRel TRel =
         (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}))"
proof (rule iffI)
  assume "fully_abstract SRel TRel"
  with preord show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
      using fully_abstract_wrt_preorders_impl_source_target_relation_is_trans[where SRel="SRel"
            and TRel="TRel"]
      unfolding preorder_on_def refl_on_def
    by auto
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                 SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                 TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                 trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
  from this obtain Rel
    where "S. (SourceTerm S, TargetTerm (S))  Rel"
      and "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      and "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
    by blast
  thus "fully_abstract SRel TRel"
      using source_target_relation_with_trans_impl_full_abstraction[where Rel="Rel"]
    by blast
qed

text ‹The same holds if to obtain transitivity the union may contain additional pairs that do
        neither relate two source nor two target terms.›

lemma (in encoding) fully_abstract_wrt_preorders_iff_source_target_relation_union_is_trans:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  shows "(fully_abstract SRel TRel  refl SRel  trans TRel) =
         (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (Rel'. ((P, Q)  Rel'. P  ProcS  Q  ProcT)
              trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel')))"
proof (rule iffI, (erule conjE)+)
  assume "fully_abstract SRel TRel" and "refl SRel" and "trans TRel"
  from this obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel"
                         and A2: "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
                         and A3: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
                         and A4: "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q})"
      using fully_abstract_wrt_preorders_impl_source_target_relation_is_trans[where SRel="SRel"
            and TRel="TRel"]
    by blast
  have "(P, Q)  {}. P  ProcS  Q  ProcT"
    by simp
  moreover from A4 have "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}  {})"
      unfolding trans_def
    by blast
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
                    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
                    (Rel'. ((P, Q)  Rel'. P  ProcS  Q  ProcT)
                       trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'))"
      using A1 A2 A3
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (Rel'. ((P, Q)  Rel'. P  ProcS  Q  ProcT)
              trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'))"
  from this obtain Rel Rel'
    where B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
      and B2: "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
      and B3: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      and B4: "(P, Q)  Rel'. P  ProcS  Q  ProcT"
      and B5: "trans (Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel')"
    by blast
  have "fully_abstract SRel TRel"
  proof auto
    fix S1 S2
    have "(TargetTerm (S1), SourceTerm S1)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    moreover assume "(S1, S2)  SRel"
    with B2 have "(SourceTerm S1, SourceTerm S2)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    moreover from B1
    have "(SourceTerm S2, TargetTerm (S2))  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    ultimately have "(TargetTerm (S1), TargetTerm (S2))  Rel  Rel'"
        using B5
        unfolding trans_def
      by blast
    with B3 B4 show "(S1, S2)  TRel"
      by blast
  next
    fix S1 S2
    from B1
    have "(SourceTerm S1, TargetTerm (S1))  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    moreover assume "(S1, S2)  TRel"
    with B3
    have "(TargetTerm (S1), TargetTerm (S2))  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    moreover
    have "(TargetTerm (S2), SourceTerm S2)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    ultimately have "(SourceTerm S1, SourceTerm S2)  Rel  Rel'"
        using B5
        unfolding trans_def
      by blast
    with B2 B4 show "(S1, S2)  SRel"
      by blast
  qed
  moreover have "refl SRel"
    unfolding refl_on_def
  proof auto
    fix S
    from B1 have "(SourceTerm S, TargetTerm (S))  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    moreover
    have "(TargetTerm (S), SourceTerm S)  Rel  {(P, Q). S. S ∈T P  S ∈S Q}  Rel'"
      by simp
    ultimately have "(SourceTerm S, SourceTerm S)  Rel  Rel'"
        using B5
        unfolding trans_def
      by blast
    with B2 B4 show "(S, S)  SRel"
      by blast
  qed
  moreover have "trans TRel"
    unfolding trans_def
  proof clarify
    fix TP TQ TR
    assume "(TP, TQ)  TRel" and "(TQ, TR)  TRel"
    with B3 B4 B5 show "(TP, TR)  TRel"
        unfolding trans_def
      by blast
  qed
  ultimately show "fully_abstract SRel TRel  refl SRel  trans TRel"
    by blast
qed

end

Theory CombinedCriteria

theory CombinedCriteria
  imports DivergenceReflection SuccessSensitiveness FullAbstraction OperationalCorrespondence
begin

section ‹Combining Criteria›

text ‹So far we considered the effect of single criteria on encodings. Often the quality of an
        encoding is prescribed by a set of different criteria. In the following we analyse the
        combined effect of criteria. This way we can compare criteria as well as identify side
        effects that result from combinations of criteria. We start with some technical lemmata. To
        combine the effect of different criteria we combine the conditions they induce. If their
        effect can be described by a predicate on the pairs of the relation, as in the case of
        success sensitiveness or divergence reflection, combining the effects is simple.›

lemma (in encoding) criterion_iff_source_target_relation_impl_indRelR:
  fixes Cond :: "('procS  'procT)  bool"
    and Pred :: "(('procS, 'procT) Proc × ('procS, 'procT) Proc) set  bool"
  assumes "Cond enc = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  Pred Rel)"
  shows "Cond enc = (Rel'. Pred (indRelR  Rel'))"
proof (rule iffI)
  assume "Cond enc"
  with assms obtain Rel where A1: "S. (SourceTerm S, TargetTerm (S))  Rel" and A2: "Pred Rel"
    by blast
  from A1 have "Rel = indRelR  (Rel - indRelR)"
    by (auto simp add: indRelR.simps)
  with A2 have "Pred (indRelR  (Rel - indRelR))"
    by simp
  thus "Rel'. Pred (indRelR  Rel')"
    by blast
next
  assume "Rel'. Pred (indRelR  Rel')"
  from this obtain Rel' where "Pred (indRelR  Rel')"
    by blast
  moreover have "S. (SourceTerm S, TargetTerm (S))  (indRelR  Rel')"
    by (simp add: indRelR.encR)
  ultimately show "Cond enc"
      using assms
    by blast
qed

lemma (in encoding) combine_conditions_on_pairs_of_relations:
  fixes RelA RelB   :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set"
    and CondA CondB :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc)  bool"
  assumes "(P, Q)  RelA. CondA (P, Q)"
      and "(P, Q)  RelB. CondB (P, Q)"
  shows "((P, Q)  RelA  RelB. CondA (P, Q))  ((P, Q)  RelA  RelB. CondB (P, Q))"
      using assms
    by blast

lemma (in encoding) combine_conditions_on_sets_of_relations:
  fixes Rel RelA :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set"
    and Cond     :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set  bool"
    and CondA    :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc)  bool"
  assumes "(P, Q)  RelA. CondA (P, Q)"
      and "Cond Rel  Rel  RelA"
  shows "Cond Rel  ((P, Q)  Rel. CondA (P, Q))"
      using assms
    by blast

lemma (in encoding) combine_conditions_on_sets_and_pairs_of_relations:
  fixes Rel RelA RelB :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set"
    and Cond          :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set  bool"
    and CondA CondB   :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc)  bool"
  assumes "(P, Q)  RelA. CondA (P, Q)"
      and "(P, Q)  RelB. CondB (P, Q)"
      and "Cond Rel  Rel  RelA  Rel  RelB"
  shows "Cond Rel  ((P, Q)  Rel. CondA (P, Q))  ((P, Q)  Rel. CondB (P, Q))"
      using assms
    by blast

text ‹We mapped several criteria on conditions on relations that relate at least all source terms
        and their literal translations. The following lemmata help us to combine such conditions by
        switching to the witness indRelR.›

lemma (in encoding) combine_conditions_on_relations_indRelR:
  fixes RelA RelB   :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set"
    and Cond        :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc) set  bool"
    and CondA CondB :: "(('procS, 'procT) Proc ×('procS, 'procT) Proc)  bool"
  assumes A1: "S. (SourceTerm S, TargetTerm (S))  RelA"
      and A2: "(P, Q)  RelA. CondA (P, Q)"
      and A3: "S. (SourceTerm S, TargetTerm (S))  RelB"
      and A4: "(P, Q)  RelB. CondB (P, Q)"
  shows "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  ((P, Q)  Rel. CondA (P, Q))
           ((P, Q)  Rel. CondB (P, Q))"
    and "Cond indRelR  (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
          ((P, Q)  Rel. CondA (P, Q))  ((P, Q)  Rel. CondB (P, Q))  Cond Rel)"
proof -
  have A5: "S. (SourceTerm S, TargetTerm (S))  indRelR"
    by (simp add: indRelR.encR)
  moreover have A6: "indRelR  RelA"
  proof clarify
    fix P Q
    assume "(P, Q)  indRelR"
    from this A1 show "(P, Q)  RelA"
      by (induct, simp)
  qed
  moreover have A7: "indRelR  RelB"
  proof clarify
    fix P Q
    assume "(P, Q)  indRelR"
    from this A3 show "(P, Q)  RelB"
      by (induct, simp)
  qed
  ultimately show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    ((P, Q)  Rel. CondA (P, Q))  ((P, Q)  Rel. CondB (P, Q))"
      using combine_conditions_on_sets_and_pairs_of_relations[where RelA="RelA" and RelB="RelB"
            and CondA="CondA" and CondB="CondB" and Rel="indRelR"
            and Cond="λR. S. (SourceTerm S, TargetTerm (S))  R"] A2 A4
    by blast
  from A2 A4 A5 A6 A7
  show "Cond indRelR  (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         ((P, Q)  Rel. CondA (P, Q))  ((P, Q)  Rel. CondB (P, Q))  Cond Rel)"
      using combine_conditions_on_sets_and_pairs_of_relations[where RelA="RelA" and RelB="RelB"
            and CondA="CondA" and CondB="CondB" and Rel="indRelR"
            and Cond="λR. S. (SourceTerm S, TargetTerm (S))  R  Cond R"]
    by blast
qed

lemma (in encoding) indRelR_cond_respects_predA_and_reflects_predB:
  fixes PredA PredB :: "('procS, 'procT) Proc  bool"
  shows "((Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA)
           (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel PredB))
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA
             rel_reflects_pred Rel PredB)"
proof (rule iffI, erule conjE)
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA"
  from this obtain RelA where A1: "S. (SourceTerm S, TargetTerm (S))  RelA"
                          and A2: "rel_respects_pred RelA PredA"
    by blast
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel PredB"
  from this obtain RelB where A3: "S. (SourceTerm S, TargetTerm (S))  RelB"
                          and A4: "rel_reflects_pred RelB PredB"
    by blast
  from A2 have "(P, Q)  RelA. PredA P  PredA Q"
    by blast
  moreover from A4 have "(P, Q)  RelB. PredB Q  PredB P"
    by blast
  ultimately have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                    ((P, Q)Rel. PredA P = PredA Q)  ((P, Q)Rel. PredB Q  PredB P)"
      using combine_conditions_on_relations_indRelR(1)[where RelA="RelA" and RelB="RelB" and
            CondA="λ(P, Q). PredA P  PredA Q" and CondB="λ(P, Q). PredB Q  PredB P"] A1 A3
    by simp
  thus "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA
         rel_reflects_pred Rel PredB"
    by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA
           rel_reflects_pred Rel PredB"
  thus "(Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_respects_pred Rel PredA) 
        (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)  rel_reflects_pred Rel PredB)"
    by blast
qed

subsection ‹Divergence Reflection and Success Sensitiveness›

text ‹We combine results on divergence reflection and success sensitiveness to analyse their
        combined effect on an encoding function. An encoding is success sensitive and reflects
        divergence iff there exists a relation that relates source terms and their literal
        translations that reflects divergence and respects success.›

lemma (in encoding_wrt_barbs) WSS_DR_iff_source_target_rel:
  fixes success :: "'barbs"
  shows "(enc_weakly_respects_barb_set {success}  enc_reflects_divergence)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof -
  have "Rel. rel_reflects_divergence Rel (STCal Source Target)
        = rel_reflects_pred Rel divergentST"
    by (simp add: divergentST_STCal_divergent)
  moreover have "Rel. (rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
                 = rel_respects_pred Rel (λP. P⇓.success))"
    by (simp add: STCalWB_reachesBarbST)
  ultimately show "(enc_weakly_respects_barb_set {success}  enc_reflects_divergence)
    = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
        rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
        rel_reflects_divergence Rel (STCal Source Target))"
      using success_sensitive_iff_source_target_rel_weakly_respects_success(1)
            divergence_reflection_iff_source_target_rel_reflects_divergence
            indRelR_cond_respects_predA_and_reflects_predB[where
              PredA="λP. P⇓.success" and PredB="divergentST"]
    by simp
qed

lemma (in encoding_wrt_barbs) SS_DR_iff_source_target_rel:
  fixes success :: "'barbs"
  shows "(enc_respects_barb_set {success}  enc_reflects_divergence)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof -
  have "Rel. rel_reflects_divergence Rel (STCal Source Target)
        = rel_reflects_pred Rel divergentST"
    by (simp add: divergentST_STCal_divergent)
  moreover have "Rel. (rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
                 = rel_respects_pred Rel (λP. P↓.success))"
    by (simp add: STCalWB_hasBarbST)
  ultimately show "(enc_respects_barb_set {success}  enc_reflects_divergence)
    = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
        rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
        rel_reflects_divergence Rel (STCal Source Target))"
      using success_sensitive_iff_source_target_rel_respects_success(1)
            divergence_reflection_iff_source_target_rel_reflects_divergence
            indRelR_cond_respects_predA_and_reflects_predB[where
              PredA="λP. P↓.success" and PredB="divergentST"]
    by simp
qed

subsection ‹Adding Operational Correspondence›

text ‹The effect of operational correspondence includes conditions (TRel is included,
        transitivity) that require a witness like indRelRTPO. In order to combine operational
        correspondence with success sensitiveness, we show that if the encoding and TRel (weakly)
        respects barbs than indRelRTPO (weakly) respects barbs. Since success is only a specific
        kind of barbs, the same holds for success sensitiveness.›

lemma (in encoding_wrt_barbs) enc_and_TRel_impl_indRelRTPO_weakly_respects_success:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  assumes encRS:  "enc_weakly_respects_barb_set {success}"
      and trelPS: "rel_weakly_preserves_barb_set TRel TWB {success}"
      and trelRS: "rel_weakly_reflects_barb_set TRel TWB {success}"
  shows "rel_weakly_respects_barb_set (indRelRTPO TRel) (STCalWB SWB TWB) {success}"
proof auto
  fix P Q P'
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "P (Calculus (STCalWB SWB TWB))* P'"
     and "P'↓<STCalWB SWB TWB>success"
  thus "Q⇓<STCalWB SWB TWB>success"
  proof (induct arbitrary: P')
    case (encR S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>success"
    hence "S⇓<SWB>success"
        using STCalWB_reachesBarbST
      by blast
    with encRS have "S⇓<TWB>success"
      by simp
    thus "TargetTerm (S)⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>success"
    thus "SourceTerm S⇓<STCalWB SWB TWB>success"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T1 (Calculus (STCalWB SWB TWB))* P'"
                and "P'↓<STCalWB SWB TWB>success"
    hence "T1⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "T2⇓<TWB>success"
        using trelPS
      by simp
    thus "TargetTerm T2⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    case (trans P Q R)
    assume "P (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>success"
       and "P'. P (Calculus (STCalWB SWB TWB))* P'  P'↓<STCalWB SWB TWB>success
             Q⇓<STCalWB SWB TWB>success"
    hence "Q⇓<STCalWB SWB TWB>success"
      by simp
    moreover assume "Q'. Q (Calculus (STCalWB SWB TWB))* Q'  Q'↓<STCalWB SWB TWB>success
                      R⇓<STCalWB SWB TWB>success"
    ultimately show "R⇓<STCalWB SWB TWB>success"
      by blast
  qed
next
  fix P Q Q'
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q (Calculus (STCalWB SWB TWB))* Q'"
     and "Q'↓<STCalWB SWB TWB>success"
  thus "P⇓<STCalWB SWB TWB>success"
  proof (induct arbitrary: Q')
    case (encR S)
    assume "TargetTerm (S) (Calculus (STCalWB SWB TWB))* Q'"
       and "Q'↓<STCalWB SWB TWB>success"
    hence "S⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
    with encRS have "S⇓<SWB>success"
        by simp
    thus "SourceTerm S⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* Q'" and "Q'↓<STCalWB SWB TWB>success"
    thus "SourceTerm S⇓<STCalWB SWB TWB>success"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T2 (Calculus (STCalWB SWB TWB))* Q'"
                and "Q'↓<STCalWB SWB TWB>success"
    hence "T2⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "T1⇓<TWB>success"
        using trelRS
      by blast
  thus "TargetTerm T1⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    case (trans P Q R R')
    assume "R (Calculus (STCalWB SWB TWB))* R'" and "R'↓<STCalWB SWB TWB>success"
       and "R'. R (Calculus (STCalWB SWB TWB))* R'  R'↓<STCalWB SWB TWB>success
             Q⇓<STCalWB SWB TWB>success"
    hence "Q⇓<STCalWB SWB TWB>success"
      by simp
    moreover assume "Q'. Q (Calculus (STCalWB SWB TWB))* Q'  Q'↓<STCalWB SWB TWB>success
                      P⇓<STCalWB SWB TWB>success"
    ultimately show "P⇓<STCalWB SWB TWB>success"
      by blast
  qed
qed

lemma (in encoding_wrt_barbs) enc_and_TRel_impl_indRelRTPO_weakly_respects_barbs:
  fixes TRel :: "('procT × 'procT) set"
  assumes encRS:  "enc_weakly_respects_barbs"
      and trelPS: "rel_weakly_preserves_barbs TRel TWB"
      and trelRS: "rel_weakly_reflects_barbs TRel TWB"
  shows "rel_weakly_respects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
proof auto
  fix P Q x P'
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "P (Calculus (STCalWB SWB TWB))* P'"
     and "P'↓<STCalWB SWB TWB>x"
  thus "Q⇓<STCalWB SWB TWB>x"
  proof (induct arbitrary: P')
    case (encR S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>x"
    hence "S⇓<SWB>x"
        using STCalWB_reachesBarbST
      by blast
    with encRS have "S⇓<TWB>x"
      by simp
    thus "TargetTerm (S)⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>x"
    thus "SourceTerm S⇓<STCalWB SWB TWB>x"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T1 (Calculus (STCalWB SWB TWB))* P'"
                and "P'↓<STCalWB SWB TWB>x"
    hence "T1⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "T2⇓<TWB>x"
        using trelPS
      by simp
    thus "TargetTerm T2⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    case (trans P Q R)
    assume "P (Calculus (STCalWB SWB TWB))* P'" and "P'↓<STCalWB SWB TWB>x"
       and "P'. P (Calculus (STCalWB SWB TWB))* P'  P'↓<STCalWB SWB TWB>x
             Q⇓<STCalWB SWB TWB>x"
    hence "Q⇓<STCalWB SWB TWB>x"
      by simp
    moreover assume "Q'. Q (Calculus (STCalWB SWB TWB))* Q'  Q'↓<STCalWB SWB TWB>x
                      R⇓<STCalWB SWB TWB>x"
    ultimately show "R⇓<STCalWB SWB TWB>x"
      by blast
  qed
next
  fix P Q x Q'
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q (Calculus (STCalWB SWB TWB))* Q'"
     and "Q'↓<STCalWB SWB TWB>x"
  thus "P⇓<STCalWB SWB TWB>x"
  proof (induct arbitrary: Q')
    case (encR S)
    assume "TargetTerm (S) (Calculus (STCalWB SWB TWB))* Q'"
       and "Q'↓<STCalWB SWB TWB>x"
    hence "S⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
    with encRS have "S⇓<SWB>x"
        by simp
    thus "SourceTerm S⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S (Calculus (STCalWB SWB TWB))* Q'" and "Q'↓<STCalWB SWB TWB>x"
    thus "SourceTerm S⇓<STCalWB SWB TWB>x"
      by blast
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T2 (Calculus (STCalWB SWB TWB))* Q'"
                and "Q'↓<STCalWB SWB TWB>x"
    hence "T2⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "T1⇓<TWB>x"
        using trelRS
      by blast
  thus "TargetTerm T1⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    case (trans P Q R R')
    assume "R (Calculus (STCalWB SWB TWB))* R'" and "R'↓<STCalWB SWB TWB>x"
       and "R'. R (Calculus (STCalWB SWB TWB))* R'  R'↓<STCalWB SWB TWB>x
             Q⇓<STCalWB SWB TWB>x"
    hence "Q⇓<STCalWB SWB TWB>x"
      by simp
    moreover assume "Q'. Q (Calculus (STCalWB SWB TWB))* Q'  Q'↓<STCalWB SWB TWB>x
                      P⇓<STCalWB SWB TWB>x"
    ultimately show "P⇓<STCalWB SWB TWB>x"
      by blast
  qed
qed

lemma (in encoding_wrt_barbs) enc_and_TRel_impl_indRelRTPO_respects_success:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  assumes encRS:  "enc_respects_barb_set {success}"
      and trelPS: "rel_preserves_barb_set TRel TWB {success}"
      and trelRS: "rel_reflects_barb_set TRel TWB {success}"
  shows "rel_respects_barb_set (indRelRTPO TRel) (STCalWB SWB TWB) {success}"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "P↓<STCalWB SWB TWB>success"
  thus "Q↓<STCalWB SWB TWB>success"
  proof induct
    case (encR S)
    assume "SourceTerm S↓<STCalWB SWB TWB>success"
    hence "S↓<SWB>success"
        using STCalWB_hasBarbST
      by blast
    with encRS have "S↓<TWB>success"
      by simp
    thus "TargetTerm (S)↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S↓<STCalWB SWB TWB>success"
    thus "SourceTerm S↓<STCalWB SWB TWB>success"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T1↓<STCalWB SWB TWB>success"
    hence "T1↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "T2↓<TWB>success"
        using trelPS
      by simp
    thus "TargetTerm T2↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    case (trans P Q R)
    assume "P↓<STCalWB SWB TWB>success"
       and "P↓<STCalWB SWB TWB>success  Q↓<STCalWB SWB TWB>success"
       and "Q↓<STCalWB SWB TWB>success  R↓<STCalWB SWB TWB>success"
    thus "R↓<STCalWB SWB TWB>success"
      by simp
  qed
next
  fix P Q
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q↓<STCalWB SWB TWB>success"
  thus "P↓<STCalWB SWB TWB>success"
  proof induct
    case (encR S)
    assume "TargetTerm (S)↓<STCalWB SWB TWB>success"
    hence "S↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
    with encRS have "S↓<SWB>success"
        by simp
    thus "SourceTerm S↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S↓<STCalWB SWB TWB>success"
    thus "SourceTerm S↓<STCalWB SWB TWB>success"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T2↓<STCalWB SWB TWB>success"
    hence "T2↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "T1↓<TWB>success"
        using trelRS
      by blast
  thus "TargetTerm T1↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    case (trans P Q R)
    assume "R↓<STCalWB SWB TWB>success"
       and "R↓<STCalWB SWB TWB>success  Q↓<STCalWB SWB TWB>success"
       and "Q↓<STCalWB SWB TWB>success  P↓<STCalWB SWB TWB>success"
    thus "P↓<STCalWB SWB TWB>success"
      by simp
  qed
qed

lemma (in encoding_wrt_barbs) enc_and_TRel_impl_indRelRTPO_respects_barbs:
  fixes TRel    :: "('procT × 'procT) set"
  assumes encRS:  "enc_respects_barbs"
      and trelPS: "rel_preserves_barbs TRel TWB"
      and trelRS: "rel_reflects_barbs TRel TWB"
  shows "rel_respects_barbs (indRelRTPO TRel) (STCalWB SWB TWB)"
proof auto
  fix P Q x
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "P↓<STCalWB SWB TWB>x"
  thus "Q↓<STCalWB SWB TWB>x"
  proof induct
    case (encR S)
    assume "SourceTerm S↓<STCalWB SWB TWB>x"
    hence "S↓<SWB>x"
        using STCalWB_hasBarbST
      by blast
    with encRS have "S↓<TWB>x"
      by simp
    thus "TargetTerm (S)↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S↓<STCalWB SWB TWB>x"
    thus "SourceTerm S↓<STCalWB SWB TWB>x"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T1↓<STCalWB SWB TWB>x"
    hence "T1↓<TWB>x"
        using STCalWB_hasBarbST
      by blast
    ultimately have "T2↓<TWB>x"
        using trelPS
      by simp
    thus "TargetTerm T2↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
  next
    case (trans P Q R)
    assume "P↓<STCalWB SWB TWB>x"
       and "P↓<STCalWB SWB TWB>x  Q↓<STCalWB SWB TWB>x"
       and "Q↓<STCalWB SWB TWB>x  R↓<STCalWB SWB TWB>x"
    thus "R↓<STCalWB SWB TWB>x"
      by simp
  qed
next
  fix P Q x
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q↓<STCalWB SWB TWB>x"
  thus "P↓<STCalWB SWB TWB>x"
  proof induct
    case (encR S)
    assume "TargetTerm (S)↓<STCalWB SWB TWB>x"
    hence "S↓<TWB>x"
        using STCalWB_hasBarbST
      by blast
    with encRS have "S↓<SWB>x"
        by simp
    thus "SourceTerm S↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
  next
    case (source S)
    assume "SourceTerm S↓<STCalWB SWB TWB>x"
    thus "SourceTerm S↓<STCalWB SWB TWB>x"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T2↓<STCalWB SWB TWB>x"
    hence "T2↓<TWB>x"
        using STCalWB_hasBarbST
      by blast
    ultimately have "T1↓<TWB>x"
        using trelRS
      by blast
  thus "TargetTerm T1↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
  next
    case (trans P Q R)
    assume "R↓<STCalWB SWB TWB>x"
       and "R↓<STCalWB SWB TWB>x  Q↓<STCalWB SWB TWB>x"
       and "Q↓<STCalWB SWB TWB>x  P↓<STCalWB SWB TWB>x"
    thus "P↓<STCalWB SWB TWB>x"
      by simp
  qed
qed

text ‹An encoding is success sensitive and operational corresponding w.r.t. a bisimulation TRel
        that respects success iff there exists a bisimultion that includes TRel and respects
        success. The same holds if we consider not only success sensitiveness but barb
        sensitiveness in general.›

lemma (in encoding_wrt_barbs) OC_SS_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding (TRel*)
           weak_reduction_bisimulation (TRel+) Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_bisimulation Rel (STCal Source Target)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def have B2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by (simp add: indRelRTPO.target)
  from Rel_def have B3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by (simp add: indRelRTPO_to_TRel(4)[where TRel="TRel"])
  from Rel_def have B4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete (TRel*)"
     and "operational_sound (TRel*)"
     and "weak_reduction_simulation (TRel+) Target"
     and "P Q Q'. (P, Q)  TRel+  Q Target* Q'
           (P'. P Target* P'  (P', Q')  TRel+)"
  with Rel_def have B5: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
         (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
         weak_reduction_bisimulation Rel (STCal Source Target)
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_bisimulation Rel (STCal Source Target)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and C2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and C3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and C4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
   and C5: "weak_reduction_bisimulation Rel (STCal Source Target)"
   and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding (TRel*)
         weak_reduction_bisimulation (TRel+) Target"
      using OC_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by auto
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using C1 C6 by blast
  hence "enc_weakly_respects_barb_set {success}"
      using success_sensitive_iff_source_target_rel_weakly_respects_success
    by auto
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  ultimately show "operational_corresponding (TRel*)
    weak_reduction_bisimulation (TRel+) Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

lemma (in encoding_wrt_barbs) OC_SS_RB_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding (TRel*)
           weak_reduction_bisimulation (TRel+) Target
           enc_weakly_respects_barbs  enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barbs TRel TWB  rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_bisimulation Rel (STCal Source Target)
             rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "rel_weakly_preserves_barbs TRel TWB" and A6: "rel_weakly_reflects_barbs TRel TWB"
     and A7: "enc_weakly_preserves_barbs" and A8: "enc_weakly_reflects_barbs"
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def have B2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by (simp add: indRelRTPO.target)
  from Rel_def have B3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by (simp add: indRelRTPO_to_TRel(4)[where TRel="TRel"])
  from Rel_def have B4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete (TRel*)"
     and "operational_sound (TRel*)"
     and "weak_reduction_simulation (TRel+) Target"
     and "P Q Q'. (P, Q)  TRel+  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel+)"
  with Rel_def have B5: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  from Rel_def A5 A6 A7 A8 have B7: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_barbs[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
         (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
         weak_reduction_bisimulation Rel (STCal Source Target)
         rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_bisimulation Rel (STCal Source Target)
           rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C: "(S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_bisimulation Rel (STCal Source Target)
           rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by auto
  hence C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by simp
  from C have C2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by simp
  from C have C3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by simp
  from C have C4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    by simp
  from C have C5: "weak_reduction_bisimulation Rel (STCal Source Target)"
    by simp
  from C have C7: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    apply (rule conjE) apply (erule conjE)+ by blast
  from C have C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule conjE) apply (erule conjE)+ by blast
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding (TRel*)
         weak_reduction_bisimulation (TRel+) Target"
      using OC_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by auto
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using C1 C6 by blast
  hence "enc_weakly_respects_barb_set {success}"
      using success_sensitive_iff_source_target_rel_weakly_respects_success
    by auto
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    apply (rule exI) using C1 C7 by blast
  hence "enc_weakly_respects_barbs"
      using enc_weakly_respects_barbs_iff_source_target_rel
    by auto
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover have "rel_weakly_respects_barbs TRel TWB"
  proof auto
    fix TP TQ x TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>x"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using C7
      by blast
    thus "TQ⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ x TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>x"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using C7
      by blast
    thus "TP⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  qed
  ultimately show "operational_corresponding (TRel*)
    weak_reduction_bisimulation (TRel+) Target
    enc_weakly_respects_barbs  enc_weakly_respects_barb_set {success}
    rel_weakly_respects_barbs TRel TWB  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

lemma (in encoding_wrt_barbs) OC_SS_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "preorder TRel"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel] preorder_on_def
    by blast
  from A5 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding refl_on_def preorder_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "operational_sound TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel)"
  with Rel_def A6 A7 have B4: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "weak_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target"
      using OC_wrt_preorder_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using C1 C6 by blast
  hence "enc_weakly_respects_barb_set {success}"
      using success_sensitive_iff_source_target_rel_weakly_respects_success
    by simp
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  ultimately show "operational_corresponding TRel  preorder TRel
    weak_reduction_bisimulation TRel Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

lemma (in encoding_wrt_barbs) OC_SS_RB_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target
           enc_weakly_respects_barbs  rel_weakly_respects_barbs TRel TWB
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barbs TRel TWB" and A2: "rel_weakly_reflects_barbs TRel TWB"
     and A3: "enc_weakly_preserves_barbs" and A4: "enc_weakly_reflects_barbs"
     and A5: "preorder TRel"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A5 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "operational_sound TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel)"
  with Rel_def A6 A7 have B4: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_barbs[where TRel="TRel"]
    by blast
  hence B7: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "weak_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target"
      using OC_wrt_preorder_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    apply (rule exI) using C1 C6 by blast
  hence "enc_weakly_respects_barbs"
      using enc_weakly_respects_barbs_iff_source_target_rel
    by simp
  moreover hence "enc_weakly_respects_barb_set {success}"
    by simp
  moreover have "rel_weakly_respects_barbs TRel TWB"
  proof auto
    fix TP TQ x TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>x"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using C6
      by blast
    thus "TQ⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ x TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>x"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using C6
      by blast
    thus "TP⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover hence "rel_weakly_respects_barb_set TRel TWB {success}"
    by blast
  ultimately show "operational_corresponding TRel  preorder TRel
    weak_reduction_bisimulation TRel Target
    enc_weakly_respects_barbs  rel_weakly_respects_barbs TRel TWB 
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

text ‹An encoding is success sensitive and weakly operational corresponding w.r.t. a
        correspondence simulation TRel that respects success iff there exists a correspondence
        simultion that includes TRel and respects success. The same holds if we consider not only
        success sensitiveness but barb sensitiveness in general.›

lemma (in encoding_wrt_barbs) WOC_SS_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding TRel  preorder TRel
           weak_reduction_correspondence_simulation TRel Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "preorder TRel"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A5 A6 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "weakly_operational_sound TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'
           (P'' Q''. P Target* P''  Q' Target* Q''  (P'', Q'')  TRel)"
  with Rel_def A6 A7 have B4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      using WOC_iff_indRelRTPO_is_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
   and C5: "preorder Rel" and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
  hence "weakly_operational_corresponding TRel  preorder TRel
          weak_reduction_correspondence_simulation TRel Target"
      using WOC_wrt_preorder_iff_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using C1 C6 by blast
  hence "enc_weakly_respects_barb_set {success}"
      using success_sensitive_iff_source_target_rel_weakly_respects_success
    by simp
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  ultimately show "weakly_operational_corresponding TRel  preorder TRel
    weak_reduction_correspondence_simulation TRel Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

lemma (in encoding_wrt_barbs) WOC_SS_RB_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding TRel  preorder TRel
           weak_reduction_correspondence_simulation TRel Target
           enc_weakly_respects_barbs  enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barbs TRel TWB  rel_weakly_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "preorder TRel"
     and A1': "rel_weakly_preserves_barbs TRel TWB" and A2': "rel_weakly_reflects_barbs TRel TWB"
     and A3': "enc_weakly_preserves_barbs" and A4': "enc_weakly_reflects_barbs"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A5 A6 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "weakly_operational_sound TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'
           (P'' Q''. P Target* P''  Q' Target* Q''  (P'', Q'')  TRel)"
  with Rel_def A6 A7 have B4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      using WOC_iff_indRelRTPO_is_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  from Rel_def A1' A2' A3' A4' have B7: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_barbs[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barbs Rel (STCalWB SWB TWB)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
   and C5: "preorder Rel" and C7: "rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
  hence "weakly_operational_corresponding TRel  preorder TRel
          weak_reduction_correspondence_simulation TRel Target"
      using WOC_wrt_preorder_iff_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barbs Rel (STCalWB SWB TWB)"
    apply (rule exI) using C1 C7 by blast
  hence D1: "enc_weakly_respects_barbs"
      using enc_weakly_respects_barbs_iff_source_target_rel
    by simp
  moreover from D1 have "enc_weakly_respects_barb_set {success}"
    by simp
  moreover have D2: "rel_weakly_respects_barbs TRel TWB"
  proof auto
    fix TP TQ x TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>x"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using C7
      by blast
    thus "TQ⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ x TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>x"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>x"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>x"
        using C7
      by blast
    thus "TP⇓<TWB>x"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover from D2 have "rel_weakly_respects_barb_set TRel TWB {success}"
    by blast
  ultimately show "weakly_operational_corresponding TRel  preorder TRel
    weak_reduction_correspondence_simulation TRel Target
    enc_weakly_respects_barbs  enc_weakly_respects_barb_set {success}
    rel_weakly_respects_barbs TRel TWB  rel_weakly_respects_barb_set TRel TWB {success}"
    by fast
qed

text ‹An encoding is strongly success sensitive and strongly operational corresponding w.r.t. a
        strong bisimulation TRel that strongly respects success iff there exists a strong
        bisimultion that includes TRel and strongly respects success. The same holds if we consider
        not only strong success sensitiveness but strong barb sensitiveness in general.›

lemma (in encoding_wrt_barbs) SOC_SS_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding TRel  preorder TRel
           strong_reduction_bisimulation TRel Target
           enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_preserves_barb_set TRel TWB {success}"
     and A2: "rel_reflects_barb_set TRel TWB {success}"
     and A3: "enc_preserves_barb_set {success}" and A4: "enc_reflects_barb_set {success}"
     and A5: "preorder TRel"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A5 A6 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "strongly_operational_complete TRel" and "strongly_operational_sound TRel"
     and "strong_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target Q'  (P'. P Target P'  (P', Q')  TRel)"
  with Rel_def A6 A7 have B4: "strong_reduction_bisimulation Rel (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_respects_success[where TRel="TRel" and success="success"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "strong_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "strongly_operational_corresponding TRel  preorder TRel
          strong_reduction_bisimulation TRel Target"
      using SOC_wrt_preorder_iff_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using C1 C6 by blast
  hence "enc_respects_barb_set {success}"
      using success_sensitive_iff_source_target_rel_respects_success
    by simp
  moreover have "rel_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP↓<TWB>success"
    hence "TargetTerm TP↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TQ↓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    fix TP TQ
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ↓<TWB>success"
    hence "TargetTerm TQ↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TP↓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
  qed
  ultimately show "strongly_operational_corresponding TRel  preorder TRel
    strong_reduction_bisimulation TRel Target
    enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success}"
    by fast
qed

lemma (in encoding_wrt_barbs) SOC_SS_RB_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding TRel  preorder TRel
           strong_reduction_bisimulation TRel Target
           enc_respects_barbs  rel_respects_barbs TRel TWB
           enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success})
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_respects_barbs Rel (STCalWB SWB TWB)
             rel_respects_barb_set Rel (STCalWB SWB TWB) {success})"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_preserves_barbs TRel TWB" and A2: "rel_reflects_barbs TRel TWB"
     and A3: "enc_preserves_barbs" and A4: "enc_reflects_barbs"
     and A5: "preorder TRel"
  from A5 have A6: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A5 have A7: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A6 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A7 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "strongly_operational_complete TRel" and "strongly_operational_sound TRel"
     and "strong_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target Q'  (P'. P Target P'  (P', Q')  TRel)"
  with Rel_def A6 A7 have B4: "strong_reduction_bisimulation Rel (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A5 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by blast
  from Rel_def A1 A2 A3 A4 have B6: "rel_respects_barbs Rel (STCalWB SWB TWB)"
      using enc_and_TRel_impl_indRelRTPO_respects_barbs[where TRel="TRel"]
    by blast
  hence B7: "rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_respects_barbs Rel (STCalWB SWB TWB)
         rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_respects_barbs Rel (STCalWB SWB TWB)
           rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
  from this obtain Rel where C1: "(S. (SourceTerm S, TargetTerm (S))  Rel)"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "(S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)"
   and C4: "strong_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_respects_barbs Rel (STCalWB SWB TWB)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel})
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "strongly_operational_corresponding TRel  preorder TRel
          strong_reduction_bisimulation TRel Target"
      using SOC_wrt_preorder_iff_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_respects_barbs Rel (STCalWB SWB TWB)"
    apply (rule exI) using C1 C6 by blast
  hence "enc_respects_barbs"
      using enc_respects_barbs_iff_source_target_rel
    by simp
  moreover hence "enc_respects_barb_set {success}"
    by simp
  moreover have "rel_respects_barbs TRel TWB"
  proof auto
    fix TP TQ x
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP↓<TWB>x"
    hence "TargetTerm TP↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TQ↓<STCalWB SWB TWB>x"
        using C6
      by blast
    thus "TQ↓<TWB>x"
        using STCalWB_hasBarbST
      by blast
  next
    fix TP TQ x
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ↓<TWB>x"
    hence "TargetTerm TQ↓<STCalWB SWB TWB>x"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TP↓<STCalWB SWB TWB>x"
        using C6
      by blast
    thus "TP↓<TWB>x"
        using STCalWB_hasBarbST
      by blast
  qed
  moreover hence "rel_respects_barb_set TRel TWB {success}"
    by blast
  ultimately show "strongly_operational_corresponding TRel  preorder TRel
    strong_reduction_bisimulation TRel Target
    enc_respects_barbs  rel_respects_barbs TRel TWB
    enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success}"
    by fast
qed

text ‹Next we also add divergence reflection to operational correspondence and success
        sensitiveness.›

lemma (in encoding) enc_and_TRelimpl_indRelRTPO_reflect_divergence:
  fixes TRel    :: "('procT × 'procT) set"
  assumes encRD:  "enc_reflects_divergence"
      and trelRD: "rel_reflects_divergence TRel Target"
  shows "rel_reflects_divergence (indRelRTPO TRel) (STCal Source Target)"
proof auto
  fix P Q
  assume "P ≲⟦⋅⟧RT<TRel> Q" and "Q (STCal Source Target)ω"
  thus "P (STCal Source Target)ω"
  proof induct
    case (encR S)
    assume "TargetTerm (S) (STCal Source Target)ω"
    hence "S (Target)ω"
      by (simp add: STCal_divergent(2))
    with encRD have "S (Source)ω"
      by simp
    thus "SourceTerm S (STCal Source Target)ω"
      by (simp add: STCal_divergent(1))
  next
    case (source S)
    assume "SourceTerm S (STCal Source Target)ω"
    thus "SourceTerm S (STCal Source Target)ω"
      by simp
  next
    case (target T1 T2)
    assume "(T1, T2)  TRel"
    moreover assume "TargetTerm T2 (STCal Source Target)ω"
    hence "T2 (Target)ω"
      by (simp add: STCal_divergent(2))
    ultimately have "T1 (Target)ω"
        using trelRD
      by blast
    thus "TargetTerm T1 (STCal Source Target)ω"
      by (simp add: STCal_divergent(2))
  next
    case (trans P Q R)
    assume "R (STCal Source Target)ω"
       and "R (STCal Source Target)ω  Q (STCal Source Target)ω"
       and "Q (STCal Source Target)ω  P (STCal Source Target)ω"
    thus "P (STCal Source Target)ω"
      by simp
  qed
qed

lemma (in encoding_wrt_barbs) OC_SS_DR_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding (TRel*)
           weak_reduction_bisimulation (TRel+) Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success}
           enc_reflects_divergence  rel_reflects_divergence TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
             (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
             weak_reduction_bisimulation Rel (STCal Source Target)
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "rel_reflects_divergence TRel Target" and A6: "enc_reflects_divergence"
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def have B2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
    by (simp add: indRelRTPO.target)
  from Rel_def have B3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
    by (simp add: indRelRTPO_to_TRel(4)[where TRel="TRel"])
  from Rel_def have B4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete (TRel*)"
     and "operational_sound (TRel*)"
     and "weak_reduction_simulation (TRel+) Target"
     and "P Q Q'. (P, Q)  TRel+  Q Target* Q'
           (P'. P Target* P'  (P', Q')  TRel+)"
  with Rel_def have B5: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  from Rel_def A5 A6 have B7: "rel_reflects_divergence Rel (STCal Source Target)"
      using enc_and_TRelimpl_indRelRTPO_reflect_divergence[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
         (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
         weak_reduction_bisimulation Rel (STCal Source Target)
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
         rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
           (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
           weak_reduction_bisimulation Rel (STCal Source Target)
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
           rel_reflects_divergence Rel (STCal Source Target)"
  from this obtain Rel where C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and C2: "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
   and C3: "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
   and C4: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
   and C5: "weak_reduction_bisimulation Rel (STCal Source Target)"
   and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
   and C7: "rel_reflects_divergence Rel (STCal Source Target)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
    (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding (TRel*)
         weak_reduction_bisimulation (TRel+) Target"
      using OC_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by auto
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
                  rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using C1 C6 C7 by blast
  hence "enc_weakly_respects_barb_set {success}  enc_reflects_divergence"
      using WSS_DR_iff_source_target_rel
    by auto
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover from C2 C7 have "rel_reflects_divergence TRel Target"
      using STCal_divergent(2)
    by blast
  ultimately show "operational_corresponding (TRel*)
    weak_reduction_bisimulation (TRel+) Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}
    enc_reflects_divergence  rel_reflects_divergence TRel Target"
    by fast
qed

lemma (in encoding_wrt_barbs) WOC_SS_DR_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(weakly_operational_corresponding TRel  preorder TRel
           weak_reduction_correspondence_simulation TRel Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success}
           enc_reflects_divergence  rel_reflects_divergence TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "rel_reflects_divergence TRel Target" and A6: "enc_reflects_divergence"
     and A7: "preorder TRel"
  from A7 have A8: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A7 have A9: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A8 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A9 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "weakly_operational_sound TRel" and "preorder TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'
           (P'' Q''. P Target* P''  Q' Target* Q''  (P'', Q'')  TRel)"
  with Rel_def A8 A9 have B4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
      using WOC_iff_indRelRTPO_is_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  from Rel_def A7 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  from Rel_def A5 A6 have B7: "rel_reflects_divergence Rel (STCal Source Target)"
      using enc_and_TRelimpl_indRelRTPO_reflect_divergence[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
         rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_correspondence_simulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
           rel_reflects_divergence Rel (STCal Source Target)"
  from this obtain Rel where C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
   and C4: "weak_reduction_correspondence_simulation Rel (STCal Source Target)"
   and C5: "preorder Rel" and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
   and C7: "rel_reflects_divergence Rel (STCal Source Target)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_correspondence_simulation Rel (STCal Source Target)"
    by blast
  hence "weakly_operational_corresponding TRel  preorder TRel
          weak_reduction_correspondence_simulation TRel Target"
      using WOC_wrt_preorder_iff_reduction_correspondence_simulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
                  rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using C1 C6 C7 by blast
  hence "enc_weakly_respects_barb_set {success}  enc_reflects_divergence"
      using WSS_DR_iff_source_target_rel
    by simp
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover from C2 C7 have "rel_reflects_divergence TRel Target"
      using STCal_divergent(2)
    by blast
  ultimately
  show "weakly_operational_corresponding TRel  preorder TRel
    weak_reduction_correspondence_simulation TRel Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}
    enc_reflects_divergence  rel_reflects_divergence TRel Target"
    by fast
qed

lemma (in encoding_wrt_barbs) OC_SS_DR_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target
           enc_weakly_respects_barb_set {success}
           rel_weakly_respects_barb_set TRel TWB {success}
           enc_reflects_divergence  rel_reflects_divergence TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_weakly_preserves_barb_set TRel TWB {success}"
     and A2: "rel_weakly_reflects_barb_set TRel TWB {success}"
     and A3: "enc_weakly_preserves_barb_set {success}"
     and A4: "enc_weakly_reflects_barb_set {success}"
     and A5: "rel_reflects_divergence TRel Target" and A6: "enc_reflects_divergence"
     and A7: "preorder TRel"
  from A7 have A8: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A7 have A9: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A8 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A9 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "operational_complete TRel" and "operational_sound TRel" and "preorder TRel"
     and "weak_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target* Q'  (P'. P Target* P'  (P', Q')  TRel)"
  with Rel_def A8 A9 have B4: "weak_reduction_bisimulation Rel (STCal Source Target)"
      using OC_iff_indRelRTPO_is_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A7 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_weakly_respects_success[where TRel="TRel"
            and success="success"]
    by blast
  from Rel_def A5 A6 have B7: "rel_reflects_divergence Rel (STCal Source Target)"
      using enc_and_TRelimpl_indRelRTPO_reflect_divergence[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
         rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           weak_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
           rel_reflects_divergence Rel (STCal Source Target)"
  from this obtain Rel where C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
   and C4: "weak_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}"
   and C7: "rel_reflects_divergence Rel (STCal Source Target)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target"
      using OC_wrt_preorder_iff_weak_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_weakly_respects_barb_set Rel (STCalWB SWB TWB) {success}
                  rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using C1 C6 C7 by blast
  hence "enc_weakly_respects_barb_set {success}  enc_reflects_divergence"
      using WSS_DR_iff_source_target_rel
    by simp
  moreover have "rel_weakly_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ TP'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP (Calculus TWB)* TP'" and "TP'↓<TWB>success"
    hence "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  next
    fix TP TQ TQ'
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ (Calculus TWB)* TQ'" and "TQ'↓<TWB>success"
    hence "TargetTerm TQ⇓<STCalWB SWB TWB>success"
        using STCalWB_reachesBarbST
      by blast
    ultimately have "TargetTerm TP⇓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP⇓<TWB>success"
        using STCalWB_reachesBarbST
      by blast
  qed
  moreover from C2 C7 have "rel_reflects_divergence TRel Target"
      using STCal_divergent(2)
    by blast
  ultimately
  show "operational_corresponding TRel  preorder TRel  weak_reduction_bisimulation TRel Target
    enc_weakly_respects_barb_set {success}  rel_weakly_respects_barb_set TRel TWB {success}
    enc_reflects_divergence  rel_reflects_divergence TRel Target"
    by fast
qed

lemma (in encoding_wrt_barbs) SOC_SS_DR_wrt_preorder_iff_source_target_rel:
  fixes success :: "'barbs"
    and TRel    :: "('procT × 'procT) set"
  shows "(strongly_operational_corresponding TRel  preorder TRel
           strong_reduction_bisimulation TRel Target
           enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success}
           enc_reflects_divergence  rel_reflects_divergence TRel Target)
         = (Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
             TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
             (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
             strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
             rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
             rel_reflects_divergence Rel (STCal Source Target))"
proof (rule iffI, (erule conjE)+)
  assume A1: "rel_preserves_barb_set TRel TWB {success}"
     and A2: "rel_reflects_barb_set TRel TWB {success}"
     and A3: "enc_preserves_barb_set {success}" and A4: "enc_reflects_barb_set {success}"
     and A5: "rel_reflects_divergence TRel Target" and A6: "enc_reflects_divergence"
     and A7: "preorder TRel"
  from A7 have A8: "TRel+ = TRel"
      using trancl_id[of TRel]
      unfolding preorder_on_def
    by blast
  from A7 have A9: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding preorder_on_def refl_on_def
    by auto
  define Rel where "Rel = indRelRTPO TRel"
  hence B1: "S. (SourceTerm S, TargetTerm (S))  Rel"
    by (simp add: indRelRTPO.encR)
  from Rel_def A8 have B2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
      using indRelRTPO_to_TRel(4)[where TRel="TRel"]
    by (auto simp add: indRelRTPO.target)
  from Rel_def A9 have B3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
      using indRelRTPO_to_TRel(2)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by simp
  assume "strongly_operational_complete TRel" and "strongly_operational_sound TRel"
     and "preorder TRel" and "strong_reduction_simulation TRel Target"
     and "P Q Q'. (P, Q)  TRel  Q Target Q'  (P'. P Target P'  (P', Q')  TRel)"
  with Rel_def A8 A9 have B4: "strong_reduction_bisimulation Rel (STCal Source Target)"
      using SOC_iff_indRelRTPO_is_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  from Rel_def A7 have B5: "preorder Rel"
      using indRelRTPO_is_preorder[where TRel="TRel"]
      unfolding preorder_on_def
    by simp
  from Rel_def A1 A2 A3 A4 have B6: "rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
      using enc_and_TRel_impl_indRelRTPO_respects_success[where TRel="TRel" and success="success"]
    by blast
  from Rel_def A5 A6 have B7: "rel_reflects_divergence Rel (STCal Source Target)"
      using enc_and_TRelimpl_indRelRTPO_reflect_divergence[where TRel="TRel"]
    by blast
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
         TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
         (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
         strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
         rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
         rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using B1 B2 B3 B4 B5 B6 B7 by blast
next
  assume "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
           TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
           (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)
           strong_reduction_bisimulation Rel (STCal Source Target)  preorder Rel
           rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
           rel_reflects_divergence Rel (STCal Source Target)"
  from this obtain Rel where C1: "S. (SourceTerm S, TargetTerm (S))  Rel"
   and C2: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and C3: "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel"
   and C4: "strong_reduction_bisimulation Rel (STCal Source Target)" and C5: "preorder Rel"
   and C6: "rel_respects_barb_set Rel (STCalWB SWB TWB) {success}"
   and C7: "rel_reflects_divergence Rel (STCal Source Target)"
    by auto
  from C1 C2 C3 C4 C5 have "Rel.(S. (SourceTerm S, TargetTerm (S))  Rel)
    TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
    (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel)  preorder Rel
    strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  hence "strongly_operational_corresponding TRel  preorder TRel
          strong_reduction_bisimulation TRel Target"
      using SOC_wrt_preorder_iff_strong_reduction_bisimulation[where TRel="TRel"]
    by simp
  moreover have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
                  rel_respects_barb_set Rel (STCalWB SWB TWB) {success}
                  rel_reflects_divergence Rel (STCal Source Target)"
    apply (rule exI) using C1 C6 C7 by blast
  hence "enc_respects_barb_set {success}  enc_reflects_divergence"
      using SS_DR_iff_source_target_rel
    by simp
  moreover have "rel_respects_barb_set TRel TWB {success}"
  proof auto
    fix TP TQ
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TP↓<TWB>success"
    hence "TargetTerm TP↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TQ↓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TQ↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
  next
    fix TP TQ
    assume "(TP, TQ)  TRel"
    with C2 have "(TargetTerm TP, TargetTerm TQ)  Rel"
      by simp
    moreover assume "TQ↓<TWB>success"
    hence "TargetTerm TQ↓<STCalWB SWB TWB>success"
        using STCalWB_hasBarbST
      by blast
    ultimately have "TargetTerm TP↓<STCalWB SWB TWB>success"
        using C6
      by blast
    thus "TP↓<TWB>success"
        using STCalWB_hasBarbST
      by blast
  qed
  moreover from C2 C7 have "rel_reflects_divergence TRel Target"
      using STCal_divergent(2)
    by blast
  ultimately show "strongly_operational_corresponding TRel  preorder TRel
    strong_reduction_bisimulation TRel Target
    enc_respects_barb_set {success}  rel_respects_barb_set TRel TWB {success}
    enc_reflects_divergence  rel_reflects_divergence TRel Target"
    by fast
qed

subsection ‹Full Abstraction and Operational Correspondence›

text ‹To combine full abstraction and operational correspondence we consider a symmetric version
        of the induced relation and assume that the relations SRel and TRel are equivalences. Then
        an encoding is fully abstract w.r.t. SRel and TRel and operationally corresponding w.r.t.
        TRel such that TRel is a bisimulation iff the induced relation contains both SRel and TRel
        and is a transitive bisimulation.›

lemma (in encoding) FS_OC_modulo_equivalences_iff_source_target_relation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes eqS: "equivalence SRel"
      and eqT: "equivalence TRel"
  shows "fully_abstract SRel TRel
          operational_corresponding TRel  weak_reduction_bisimulation TRel Target
          (Rel.
         (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
          trans Rel  weak_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE, erule conjE)
  assume A1: "fully_abstract SRel TRel" and A2: "operational_corresponding TRel"
     and A3: "weak_reduction_bisimulation TRel Target"
  from eqT have A4: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding equiv_def refl_on_def
    by auto
  have A5:
   "S. SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)  TargetTerm (S) ∼⟦⋅⟧T<TRel> SourceTerm S"
    by (simp add: indRelTEQ.encR indRelTEQ.encL)
  moreover from A4 have A6: "TRel = {(T1, T2). TargetTerm T1 ∼⟦⋅⟧T<TRel> TargetTerm T2}"
      using indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by (auto simp add: indRelTEQ.target)
  moreover have A7: "trans (indRelTEQ TRel)"
      using indRelTEQ.trans[where TRel="TRel"]
      unfolding trans_def
    by blast
  moreover have "SRel = {(S1, S2). SourceTerm S1 ∼⟦⋅⟧T<TRel> SourceTerm S2}"
  proof -
    from A6 have "S1 S2. ((S1, S2)  TRel) = TargetTerm (S1) ∼⟦⋅⟧T<TRel> TargetTerm (S2)"
      by blast
    moreover have "indRelTEQ TRel  {(P, Q). S. S ∈T P  S ∈S Q} = indRelTEQ TRel"
      by (auto simp add: indRelTEQ.encL)
    with A7 have "trans (indRelTEQ TRel  {(P, Q). S. S ∈T P  S ∈S Q})"
        unfolding trans_def
      by blast
    ultimately show "SRel = {(S1, S2). SourceTerm S1 ∼⟦⋅⟧T<TRel> SourceTerm S2}"
        using A1 A5 full_abstraction_and_trans_relation_contains_TRel_impl_SRel[where
                    SRel="SRel" and TRel="TRel" and Rel="indRelTEQ TRel"]
      by blast
  qed
  moreover from eqT A2 A3 have "weak_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
      using OC_wrt_equivalence_iff_indRelTEQ_weak_reduction_bisimulation[where TRel="TRel"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
          trans Rel  weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume
   "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
     SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
     TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}
     trans Rel  weak_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where
       B1: "S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel"
   and B2: "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
   and B3: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}"
   and B4: "trans Rel" and B5: "weak_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  from B1 B2 B3 B4 have "fully_abstract SRel TRel"
      using trans_source_target_relation_impl_fully_abstract[where Rel="Rel" and SRel="SRel"
            and TRel="TRel"]
    by blast
  moreover have "operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
  proof -
    from eqT have C1: "TRel+ = TRel"
        using trancl_id[of TRel]
        unfolding equiv_def
      by blast
    from eqT have C2: "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover from B3 have "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      by simp
    moreover from B3 C1 have "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
      by simp
    moreover have "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    proof clarify
      fix S T
      from B1 have "(TargetTerm (S), SourceTerm S)  Rel"
        by simp
      moreover assume "(SourceTerm S, TargetTerm T)  Rel"
      ultimately have "(TargetTerm (S), TargetTerm T)  Rel"
          using B4
          unfolding trans_def
        by blast
      with B3 C2 show "(S, T)  TRel*"
        by simp
    qed
    ultimately have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
      (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
      (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
      (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
      weak_reduction_bisimulation Rel (STCal Source Target)"
           using B5
         by blast
    with C1 C2 show "operational_corresponding TRel  weak_reduction_bisimulation TRel Target"
        using OC_iff_weak_reduction_bisimulation[where TRel="TRel"]
      by auto
  qed
  ultimately show "fully_abstract SRel TRel  operational_corresponding TRel
                    weak_reduction_bisimulation TRel Target"
    by simp
qed

lemma (in encoding) FA_SOC_modulo_equivalences_iff_source_target_relation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes eqS: "equivalence SRel"
      and eqT: "equivalence TRel"
  shows "fully_abstract SRel TRel  strongly_operational_corresponding TRel
          strong_reduction_bisimulation TRel Target  (Rel.
         (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
          strong_reduction_bisimulation Rel (STCal Source Target))"
proof (rule iffI, erule conjE, erule conjE)
  assume A1: "fully_abstract SRel TRel" and A2: "strongly_operational_corresponding TRel"
     and A3: "strong_reduction_bisimulation TRel Target"
  from eqT have A4: "TRel* = TRel"
      using reflcl_trancl[of TRel] trancl_id[of TRel]
      unfolding equiv_def refl_on_def
    by auto
  have A5:
   "S. SourceTerm S ∼⟦⋅⟧T<TRel> TargetTerm (S)  TargetTerm (S) ∼⟦⋅⟧T<TRel> SourceTerm S"
    by (simp add: indRelTEQ.encR indRelTEQ.encL)
  moreover from A4 have A6: "TRel = {(T1, T2). TargetTerm T1 ∼⟦⋅⟧T<TRel> TargetTerm T2}"
      using indRelTEQ_to_TRel(4)[where TRel="TRel"]
            trans_closure_of_TRel_refl_cond[where TRel="TRel"]
    by (auto simp add: indRelTEQ.target)
  moreover have A7: "trans (indRelTEQ TRel)"
      using indRelTEQ.trans[where TRel="TRel"]
      unfolding trans_def
    by blast
  moreover have "SRel = {(S1, S2). SourceTerm S1 ∼⟦⋅⟧T<TRel> SourceTerm S2}"
  proof -
    from A6 have "S1 S2. ((S1, S2)  TRel) = TargetTerm (S1) ∼⟦⋅⟧T<TRel> TargetTerm (S2)"
      by blast
    moreover have "indRelTEQ TRel  {(P, Q). S. S ∈T P  S ∈S Q} = indRelTEQ TRel"
      by (auto simp add: indRelTEQ.encL)
    with A7 have "trans (indRelTEQ TRel  {(P, Q). S. S ∈T P  S ∈S Q})"
        unfolding trans_def
      by blast
    ultimately show "SRel = {(S1, S2). SourceTerm S1 ∼⟦⋅⟧T<TRel> SourceTerm S2}"
        using A1 A5 full_abstraction_and_trans_relation_contains_TRel_impl_SRel[where
                    SRel="SRel" and TRel="TRel" and Rel="indRelTEQ TRel"]
      by blast
  qed
  moreover from eqT A2 A3 have "strong_reduction_bisimulation (indRelTEQ TRel) (STCal Source Target)"
      using SOC_wrt_equivalence_iff_indRelTEQ_strong_reduction_bisimulation[where TRel="TRel"]
    by blast
  ultimately
  show "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
          SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
          TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
          strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
next
  assume
   "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel)
     SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}
     TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}  trans Rel
     strong_reduction_bisimulation Rel (STCal Source Target)"
  from this obtain Rel where
       B1: "S. (SourceTerm S, TargetTerm (S))  Rel  (TargetTerm (S), SourceTerm S)  Rel"
   and B2: "SRel = {(S1, S2). (SourceTerm S1, SourceTerm S2)  Rel}"
   and B3: "TRel = {(T1, T2). (TargetTerm T1, TargetTerm T2)  Rel}" and B4: "trans Rel"
   and B5: "strong_reduction_bisimulation Rel (STCal Source Target)"
    by blast
  from B1 B2 B3 B4 have "fully_abstract SRel TRel"
      using trans_source_target_relation_impl_fully_abstract[where Rel="Rel" and SRel="SRel"
            and TRel="TRel"]
    by blast
  moreover
  have "strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target"
  proof -
    from eqT have C1: "TRel+ = TRel"
        using trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by blast
    from eqT have C2: "TRel* = TRel"
        using reflcl_trancl[of TRel] trancl_id[of TRel]
        unfolding equiv_def refl_on_def
      by auto
    from B1 have "S. (SourceTerm S, TargetTerm (S))  Rel"
      by simp
    moreover from B3 have "T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel"
      by simp
    moreover from B3 C1
    have "T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+"
      by simp
    moreover have "S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*"
    proof clarify
      fix S T
      from B1 have "(TargetTerm (S), SourceTerm S)  Rel"
        by simp
      moreover assume "(SourceTerm S, TargetTerm T)  Rel"
      ultimately have "(TargetTerm (S), TargetTerm T)  Rel"
          using B4
          unfolding trans_def
        by blast
      with B3 C2 show "(S, T)  TRel*"
        by simp
    qed
    ultimately have "Rel. (S. (SourceTerm S, TargetTerm (S))  Rel)
      (T1 T2. (T1, T2)  TRel  (TargetTerm T1, TargetTerm T2)  Rel)
      (T1 T2. (TargetTerm T1, TargetTerm T2)  Rel  (T1, T2)  TRel+)
      (S T. (SourceTerm S, TargetTerm T)  Rel  (S, T)  TRel*)
      strong_reduction_bisimulation Rel (STCal Source Target)"
           using B5
         by blast
    with C1 C2
    show "strongly_operational_corresponding TRel  strong_reduction_bisimulation TRel Target"
        using SOC_iff_strong_reduction_bisimulation[where TRel="TRel"]
      by auto
  qed
  ultimately show "fully_abstract SRel TRel  strongly_operational_corresponding TRel
                    strong_reduction_bisimulation TRel Target"
    by simp
qed

text ‹An encoding that is fully abstract w.r.t. the equivalences SRel and TRel and operationally
        corresponding w.r.t. TRel ensures that SRel is a bisimulation iff TRel is a bisimulation.
›

lemma (in encoding) FA_and_OC_and_TRel_impl_SRel_bisimulation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and opCom:   "operational_complete TRel"
      and opSou:   "operational_sound TRel"
      and symmT:   "sym TRel"
      and transT:  "trans TRel"
      and bisimT:  "weak_reduction_bisimulation TRel Target"
  shows "weak_reduction_bisimulation SRel Source"
proof auto
  fix SP SQ SP'
  assume "SP Source* SP'"
  with opCom obtain TP' where A1: "SP Target* TP'" and A2: "(SP', TP')  TRel"
    by blast
  assume "(SP, SQ)  SRel"
  with fullAbs have "(SP, SQ)  TRel"
    by simp
  with bisimT A1 obtain TQ' where A3: "SQ Target* TQ'" and A4: "(TP', TQ')  TRel"
    by blast
  from A3 opSou obtain SQ' where A5: "SQ Source* SQ'" and A6: "(SQ', TQ')  TRel"
    by blast
  from A2 A4 A6 symmT transT have "(SP', SQ')  TRel"
      unfolding trans_def sym_def
    by blast
  with fullAbs A5 show "SQ'. SQ Source* SQ'  (SP', SQ')  SRel"
    by blast
next
  fix SP SQ SQ'
  assume "SQ Source* SQ'"
  with opCom obtain TQ' where B1: "SQ Target* TQ'" and B2: "(SQ', TQ')  TRel"
    by blast
  assume "(SP, SQ)  SRel"
  with fullAbs have "(SP, SQ)  TRel"
    by simp
  with bisimT B1 obtain TP' where B3: "SP Target* TP'" and B4: "(TP', TQ')  TRel"
    by blast
  from B3 opSou obtain SP' where B5: "SP Source* SP'" and B6: "(SP', TP')  TRel"
    by blast
  from B2 B4 B6 symmT transT have "(SP', SQ')  TRel"
      unfolding trans_def sym_def
    by blast
  with fullAbs B5 show "SP'. SP Source* SP'  (SP', SQ')  SRel"
    by blast
qed

lemma (in encoding) FA_and_SOC_and_TRel_impl_SRel_strong_bisimulation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and opCom:   "strongly_operational_complete TRel"
      and opSou:   "strongly_operational_sound TRel"
      and symmT:   "sym TRel"
      and transT:  "trans TRel"
      and bisimT:  "strong_reduction_bisimulation TRel Target"
  shows "strong_reduction_bisimulation SRel Source"
proof auto
  fix SP SQ SP'
  assume "SP Source SP'"
  with opCom obtain TP' where A1: "SP Target TP'" and A2: "(SP', TP')  TRel"
    by blast
  assume "(SP, SQ)  SRel"
  with fullAbs have "(SP, SQ)  TRel"
    by simp
  with bisimT A1 obtain TQ' where A3: "SQ Target TQ'" and A4: "(TP', TQ')  TRel"
    by blast
  from A3 opSou obtain SQ' where A5: "SQ Source SQ'" and A6: "(SQ', TQ')  TRel"
    by blast
  from A2 A4 A6 symmT transT have "(SP', SQ')  TRel"
      unfolding trans_def sym_def
    by blast
  with fullAbs A5 show "SQ'. SQ Source SQ'  (SP', SQ')  SRel"
    by blast
next
  fix SP SQ SQ'
  assume "SQ Source SQ'"
  with opCom obtain TQ' where B1: "SQ Target TQ'" and B2: "(SQ', TQ')  TRel"
    by blast
  assume "(SP, SQ)  SRel"
  with fullAbs have "(SP, SQ)  TRel"
    by simp
  with bisimT B1 obtain TP' where B3: "SP Target TP'" and B4: "(TP', TQ')  TRel"
    by blast
  from B3 opSou obtain SP' where B5: "SP Source SP'" and B6: "(SP', TP')  TRel"
    by blast
  from B2 B4 B6 symmT transT have "(SP', SQ')  TRel"
      unfolding trans_def sym_def
    by blast
  with fullAbs B5 show "SP'. SP Source SP'  (SP', SQ')  SRel"
    by blast
qed

lemma (in encoding) FA_and_OC_impl_SRel_iff_TRel_bisimulation:
  fixes SRel :: "('procS × 'procS) set"
    and TRel :: "('procT × 'procT) set"
  assumes fullAbs: "fully_abstract SRel TRel"
      and opCor:   "operational_corresponding TRel"
      and symmT:   "sym TRel"
      and transT:  "trans TRel"
      and surj:    "T. S. T = S"
  shows "weak_reduction_bisimulation SRel Source  weak_reduction_bisimulation TRel Target"
proof
  assume bisimS: "weak_reduction_bisimulation SRel Source"
  have "weak_reduction_simulation TRel Target"
  proof clarify
    fix TP TQ TP'
    from surj have "S. TP = S"
      by simp
    from this obtain SP where A1: "SP = TP"
      by blast
    from surj have "S. TQ = S"
      by simp
    from this obtain SQ where A2: "SQ = TQ"
      by blast
    assume "TP Target* TP'"
    with opCor A1 obtain SP' where A3: "SP Source* SP'" and A4: "(SP', TP')  TRel"
      by blast
    assume "(TP, TQ)  TRel"
    with fullAbs A1 A2 have "(SP, SQ)  SRel"
      by simp
    with bisimS A3 obtain SQ' where A5: "SQ Source* SQ'" and A6: "(SP', SQ')  SRel"
      by blast
    from opCor A2 A5 obtain TQ' where A7: "TQ Target* TQ'" and A8: "(SQ', TQ')  TRel"
      by blast
    from symmT A4 have "(TP', SP')  TRel"
        unfolding sym_def
      by simp
    moreover from fullAbs A6 have "(SP', SQ')  TRel"
      by simp
    ultimately have "(TP', TQ')  TRel"
        using transT A8
        unfolding trans_def
      by blast
    with A7 show "TQ'. TQ Target* TQ'  (TP', TQ')  TRel"
      by blast
  qed
  with symmT show "weak_reduction_bisimulation TRel Target"
      using symm_weak_reduction_simulation_is_bisimulation[where Rel="TRel" and Cal="Target"]
    by blast
next
  assume "weak_reduction_bisimulation TRel Target"
  with fullAbs opCor symmT transT show "weak_reduction_bisimulation SRel Source"
      using FA_and_OC_and_TRel_impl_SRel_bisimulation[where SRel="SRel" and TRel="TRel"]
    by blast
qed

end